pax_global_header00006660000000000000000000000064126416302410014511gustar00rootroot0000000000000052 comment=062297e0d9f00f1c7c40f98cb89c65b7fdff84d7 libfreenect-0.5.3/000077500000000000000000000000001264163024100140005ustar00rootroot00000000000000libfreenect-0.5.3/.gitattributes000066400000000000000000000000421264163024100166670ustar00rootroot00000000000000wrappers/python/freenect.c binary libfreenect-0.5.3/.gitignore000066400000000000000000000005361264163024100157740ustar00rootroot00000000000000#ignore thumbnails created by windows Thumbs.db #ignore Desktop Service Store files created by mac *.DS_Store #Ignore files build by Visual Studio *.obj *.exe *.pdb *.user *.aps *.pch *.vspscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.bak *.cache *.ilk *.log [Bb]in [Dd]ebug*/ *.lib *.sbr obj/ [Rr]elease*/ _ReSharper*/ [Tt]est[Rr]esult* build /results/ libfreenect-0.5.3/APACHE20000066400000000000000000000261361264163024100150160ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. libfreenect-0.5.3/CMakeLists.txt000066400000000000000000000174371264163024100165540ustar00rootroot00000000000000###################################################################################### # License ###################################################################################### # This file is part of the OpenKinect Project. http://www.openkinect.org # # Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file # for details. # # This code is licensed to you under the terms of the Apache License, version # 2.0, or, at your option, the terms of the GNU General Public License, # version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, # or the following URLs: # http://www.apache.org/licenses/LICENSE-2.0 # http://www.gnu.org/licenses/gpl-2.0.txt # # If you redistribute this file in source form, modified or unmodified, you # may: # 1) Leave this header intact and distribute it under the same terms, # accompanying it with the APACHE20 and GPL20 files, or # 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or # 3) Delete the GPL v2 clause and accompany it with the APACHE20 file # In all cases you must keep the copyright notice intact and include a copy # of the CONTRIB file. # # Binary distributions must follow the binary distribution requirements of # either License. ###################################################################################### # CMake directives ###################################################################################### cmake_minimum_required(VERSION 2.6) set(PYTHON_EXECUTABLE "python2") ###################################################################################### # Project declaration and options ###################################################################################### PROJECT(libfreenect) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") # Find the host operating system and architecture include (FindOS) # Set up installation directories include (SetupDirectories) set (PROJECT_VER_MAJOR 0) set (PROJECT_VER_MINOR 5) set (PROJECT_VER_PATCH 3) set (PROJECT_VER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}.${PROJECT_VER_PATCH}") set (PROJECT_APIVER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}") OPTION(BUILD_REDIST_PACKAGE "Build libfreenect in a legally-redistributable manner (only affects audio)" ON) OPTION(BUILD_EXAMPLES "Build example programs" ON) OPTION(BUILD_FAKENECT "Build fakenect mock library" ON) OPTION(BUILD_C_SYNC "Build c synchronous library" ON) OPTION(BUILD_CPP "Build C++ Library (currently header only)" ON) OPTION(BUILD_CV "Build OpenCV wrapper" OFF) OPTION(BUILD_AS3_SERVER "Build the Actionscript 3 Server Example" OFF) OPTION(BUILD_PYTHON "Build Python extension" OFF) OPTION(BUILD_OPENNI2_DRIVER "Build libfreenect driver for OpenNI2" OFF) IF(PROJECT_OS_LINUX) OPTION(BUILD_CPACK_DEB "Build an DEB using CPack" OFF) OPTION(BUILD_CPACK_RPM "Build an RPM using CPack" OFF) OPTION(BUILD_CPACK_TGZ "Build an TGZ using CPack" OFF) ENDIF(PROJECT_OS_LINUX) ###################################################################################### # Dependencies and Definitions ###################################################################################### # Find packages needed to build library find_package(libusb-1.0 REQUIRED) # Check the endianness of the system include (TestBigEndian) test_big_endian(BIG_ENDIAN) if(BIG_ENDIAN) add_definitions(-DFN_BIGENDIAN) endif() if (WIN32) set(MATH_LIB "") else(WIN32) set(MATH_LIB "m") endif() ###################################################################################### # CMake ###################################################################################### SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) SET(DOC_OUTPUT_PATH ${CMAKE_BINARY_DIR}/doc) if (MSVC) set(C_FLAGS_WARNING "-W4") else () set(C_FLAGS_WARNING "-Wall") endif (MSVC) set(C_CXX_FLAGS_DEFAULT "${C_FLAGS_WARNING} -O2") # These defaults can be overriden by -DCMAKE_C_FLAGS="" set(CMAKE_C_FLAGS "${C_CXX_FLAGS_DEFAULT} ${CMAKE_C_FLAGS}") # C Configurations SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g -DDEBUG=1") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} -g") # These defaults can be overriden by -DCMAKE_CXX_FLAGS="" set(CMAKE_CXX_FLAGS "${C_CXX_FLAGS_DEFAULT} ${CMAKE_CXX_FLAGS}") # C++ Configurations SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g -DDEBUG=1") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -g") # Pretty much everyone is going to need the main includes include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) # libfreenect.h includes libusb.h, so everyone needs this too include_directories(${LIBUSB_1_INCLUDE_DIRS}) if(WIN32) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/platform/windows") endif() # Add library project add_subdirectory (src) IF(BUILD_EXAMPLES) add_subdirectory (examples) ENDIF() IF(BUILD_FAKENECT) add_subdirectory (fakenect) ENDIF() IF(BUILD_C_SYNC) add_subdirectory (wrappers/c_sync) ENDIF() IF(BUILD_CPP) add_subdirectory (wrappers/cpp) ENDIF() IF(BUILD_CV) add_subdirectory (wrappers/opencv) ENDIF() IF(BUILD_AS3_SERVER) add_subdirectory(wrappers/actionscript) ENDIF() IF(BUILD_PYTHON) add_subdirectory (wrappers/python) ENDIF() IF(BUILD_OPENNI2_DRIVER) add_subdirectory(OpenNI2-FreenectDriver) ENDIF() ###################################################################################### # Extras ###################################################################################### # Create an uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/UninstallTarget.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/UninstallTarget.cmake" IMMEDIATE @ONLY) # --- cmake config file --- CONFIGURE_FILE(libfreenectConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libfreenectConfig.cmake @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libfreenectConfig.cmake DESTINATION share/${PROJECT_NAME}) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/UninstallTarget.cmake) # Create Debian/RPM Packages # after make, use "fakeroot cpack" in the build Dir to complete IF ( BUILD_CPACK_TGZ OR BUILD_CPACK_DEB OR BUILD_CPACK_RPM ) set(CPACK_PACKAGE_DESCRIPTION "libfreenect for kinect") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "libfreenect library for using kinect") set(CPACK_PACKAGE_NAME "libfreenect-dev") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libusb-1.0-0-dev") set(CPACK_PACKAGE_CONTACT "OpenKinect ") #set(CPACK_PACKAGE_VENDOR "") set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VER_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VER_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VER_PATCH}) set(VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_GENERATOR "") if (BUILD_CPACK_TGZ) list(APPEND CPACK_GENERATOR "TGZ") endif() if (BUILD_CPACK_RPM) list(APPEND CPACK_GENERATOR "RPM") endif() if (BUILD_CPACK_DEB) list(APPEND CPACK_GENERATOR "DEB") endif() set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}-${CMAKE_SYSTEM_PROCESSOR}") include(CPack) INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/libfreenect.a" DESTINATION ${PROJECT_LIBRARY_INSTALL_DIR}) INSTALL(FILES "include/libfreenect.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) INSTALL(FILES "include/libfreenect_registration.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) INSTALL(FILES "include/libfreenect_audio.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) INSTALL(FILES "APACHE20" DESTINATION "share/doc/${CPACK_PACKAGE_NAME}") INSTALL(FILES "GPL2" DESTINATION "share/doc/${CPACK_PACKAGE_NAME}") INSTALL(FILES "README.md" DESTINATION "share/doc/${CPACK_PACKAGE_NAME}") ENDIF ( ) libfreenect-0.5.3/CONTRIB000066400000000000000000000036521264163024100150310ustar00rootroot00000000000000The following people have contributed to libfreenect: Aditya Gaddam Alex Weiss Andrew Antonio Ospite arnebe Benn Snyder Ben Stolovitz Brandyn A. White Chris J (cryptk) David García Garzón Dominick D'Aniello Drew Fisher Eric Monti Erwan Daubert Evan Shelhamer Florian Echtler Francois Coulombe Gabor Szarka Hector Martin James Harris Joakim Gebart Jochen Kerdels John Scheible josephd Josh Grunzweig Joshua Blake Juan Carlos del Valle Kai Ritterbusch Kai R Kelvie Wong Kenneth Johansson Kyle Machulis Marcos Paulo Berteli Slomp Mark Renouf Melonee Wise Nicolas Bourdaud Peter Kropf Radu Bogdan Rusu Rich Mattes Robert Xiao Stéphane Magnenat Stephen Sinclair Steven Lovegrove Theo Watson Thomas Roefer Tim Niemueller Tully Foote Vincent Le Ligeour Yannis Gravezas Yaroslav Halchenko libfreenect-0.5.3/GPL2000066400000000000000000000431331264163024100144330ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, 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 St, 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. libfreenect-0.5.3/OpenNI2-FreenectDriver/000077500000000000000000000000001264163024100201175ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/CMakeLists.txt000066400000000000000000000017241264163024100226630ustar00rootroot00000000000000###################################################################################### # OpenNI2-FreenectDriver ###################################################################################### file(GLOB HEADERS src/*.hpp src/*.h) file(GLOB SOURCES src/*.cpp) add_library(FreenectDriver SHARED ${HEADERS} ${SOURCES}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function") set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/OpenNI2-FreenectDriver) set_target_properties(FreenectDriver PROPERTIES VERSION ${PROJECT_VER} SOVERSION ${PROJECT_APIVER} OUTPUT_NAME FreenectDriver) add_definitions(-DPROJECT_VER="${PROJECT_VER}") include_directories(extern/OpenNI-Linux-x64-2.2.0.33/Include) include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/wrappers/cpp) target_link_libraries(FreenectDriver freenectstatic ${MATH_LIB}) install (TARGETS FreenectDriver DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}/OpenNI2-FreenectDriver") libfreenect-0.5.3/OpenNI2-FreenectDriver/README.md000066400000000000000000000057611264163024100214070ustar00rootroot00000000000000OpenNI2-FreenectDriver ====================== OpenNI2-FreenectDriver is a bridge to libfreenect implemented as an OpenNI2 driver. It allows OpenNI2 to use Kinect hardware on Linux and OSX. OpenNI2-FreenectDriver is distributed under the [Apache 2](https://github.com/OpenKinect/libfreenect/blob/master/APACHE20) license. Install ------- 1. Download and unpack [OpenNI](http://structure.io/openni) 2.2.0.33 or higher. 2. Go to the top libfreenect directory and build it with the OpenNI2 driver. mkdir build cd build cmake .. -DBUILD_OPENNI2_DRIVER=ON make 3. Copy the driver to your OpenNI2 driver repository. You must first change `Repository` to match your project layout. Repository="/example/path/to/Samples/Bin/OpenNI2/Drivers/" cp -L lib/OpenNI2-FreenectDriver/libFreenectDriver.{so,dylib} ${Repository} # you could instead make a symlink to avoid copying after every build # ln -s lib/OpenNI2-FreenectDriver/libFreenectDriver.{so,dylib} ${Repository} OpenNI2-FreenectDriver is built with a static libfreenect, so you do not need to include libfreenect when deploying. However, you will need to make sure target systems have libusb and all other dependencies listed in `ldd libFreenectDriver.so`. __________________________________________________ Structure --------- This driver is modeled on TestDevice.cpp and Drivers/Kinect/. In the FreenectDriver namespace, it ties together the C++ interfaces of OpenNI2 and libfreenect using multiple inheritance. Driver inherits publically from oni::driver::DriverBase and privately from Freenect::Freenect. libfreenect.hpp allows protected access to the Freenect context, so that FreenectDriver can call the Freenect's C API. As a DriverBase, FreenectDriver manages devices and sets up device state callbacks. Device inherits publically from oni::driver::DeviceBase and Freenect::FreenectDevice. Because of this, it can be built by Freenect::Freenect::createDevice() and it can define Device's depth and video callbacks. Those callbacks trigger acquireFrame() in FreenectStream. VideoStream is a virtual base class inheriting from oni::driver::StreamBase. It does generic frame setup in buildFrame() and then calls pure virtual populateFrame() to let derived classes finish the frame. It also provides the base skeleton for setting and getting properties, which cascades down the inheritance tree. DepthStream and ColorStream are nearly identical in definition and implementation, both inheriting from VideoStream. They differ mostly in the formats they use to process data and the video modes they support. These two classes offer a system to store and report supported video modes. To implement a new mode, simply add it to getSupportedVideoModes() and modify populateFrame() as necessary. __________________________________________________ Todo ---- * support more FREENECT_RESOLUTION_\*, FREENECT_VIDEO_\*, and FREENECT_DEPTH_\* * provide more OniVideoMode and OniStreamProperty * implement remaining derived functions libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/000077500000000000000000000000001264163024100214245ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/000077500000000000000000000000001264163024100251515ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/000077500000000000000000000000001264163024100265345ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Android-Arm/000077500000000000000000000000001264163024100306315ustar00rootroot00000000000000OniPlatformAndroid-Arm.h000066400000000000000000000043721264163024100352010ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Android-Arm/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PLATFORM_ANDROID_ARM_H_ #define _ONI_PLATFORM_ANDROID_ARM_H_ // Start with Linux-x86, and override what's different #include "../Linux-x86/OniPlatformLinux-x86.h" //--------------------------------------------------------------------------- // Platform Basic Definition //--------------------------------------------------------------------------- #undef ONI_PLATFORM #undef ONI_PLATFORM_STRING #define ONI_PLATFORM ONI_PLATFORM_ANDROID_ARM #define ONI_PLATFORM_STRING "Android-Arm" #ifdef HAVE_ANDROID_OS #define ONI_PLATFORM_ANDROID_OS #undef ONI_PLATFORM_STRING #define ONI_PLATFORM_STRING "AndroidOS-Arm" #endif #endif //_ONI_PLATFORM_LINUX_ARM_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Driver/000077500000000000000000000000001264163024100277675ustar00rootroot00000000000000OniDriverAPI.h000066400000000000000000000440541264163024100323230ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Driver/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_DRIVER_API_H_ #define _ONI_DRIVER_API_H_ #include "OniPlatform.h" #include "OniCTypes.h" #include "OniCProperties.h" #include "OniDriverTypes.h" #include namespace oni { namespace driver { class DeviceBase; class StreamBase; typedef void (ONI_CALLBACK_TYPE* DeviceConnectedCallback)(const OniDeviceInfo*, void* pCookie); typedef void (ONI_CALLBACK_TYPE* DeviceDisconnectedCallback)(const OniDeviceInfo*, void* pCookie); typedef void (ONI_CALLBACK_TYPE* DeviceStateChangedCallback)(const OniDeviceInfo* deviceId, int errorState, void* pCookie); typedef void (ONI_CALLBACK_TYPE* NewFrameCallback)(StreamBase* streamId, OniFrame*, void* pCookie); typedef void (ONI_CALLBACK_TYPE* PropertyChangedCallback)(void* sender, int propertyId, const void* data, int dataSize, void* pCookie); class StreamServices : public OniStreamServices { public: int getDefaultRequiredFrameSize() { return OniStreamServices::getDefaultRequiredFrameSize(streamServices); } OniFrame* acquireFrame() { return OniStreamServices::acquireFrame(streamServices); } void addFrameRef(OniFrame* pFrame) { OniStreamServices::addFrameRef(streamServices, pFrame); } void releaseFrame(OniFrame* pFrame) { OniStreamServices::releaseFrame(streamServices, pFrame); } }; class StreamBase { public: StreamBase() : m_newFrameCallback(NULL), m_propertyChangedCallback(NULL) {} virtual ~StreamBase() {} virtual void setServices(StreamServices* pStreamServices) { m_pServices = pStreamServices; } virtual OniStatus setProperty(int /*propertyId*/, const void* /*data*/, int /*dataSize*/) {return ONI_STATUS_NOT_IMPLEMENTED;} virtual OniStatus getProperty(int /*propertyId*/, void* /*data*/, int* /*pDataSize*/) {return ONI_STATUS_NOT_IMPLEMENTED;} virtual OniBool isPropertySupported(int /*propertyId*/) {return FALSE;} virtual OniStatus invoke(int /*commandId*/, void* /*data*/, int /*dataSize*/) {return ONI_STATUS_NOT_IMPLEMENTED;} virtual OniBool isCommandSupported(int /*commandId*/) {return FALSE;} virtual int getRequiredFrameSize() { return getServices().getDefaultRequiredFrameSize(); } virtual OniStatus start() = 0; virtual void stop() = 0; virtual void setNewFrameCallback(NewFrameCallback handler, void* pCookie) { m_newFrameCallback = handler; m_newFrameCallbackCookie = pCookie; } virtual void setPropertyChangedCallback(PropertyChangedCallback handler, void* pCookie) { m_propertyChangedCallback = handler; m_propertyChangedCookie = pCookie; } virtual void notifyAllProperties() { return; } virtual OniStatus convertDepthToColorCoordinates(StreamBase* /*colorStream*/, int /*depthX*/, int /*depthY*/, OniDepthPixel /*depthZ*/, int* /*pColorX*/, int* /*pColorY*/) { return ONI_STATUS_NOT_SUPPORTED; } protected: void raiseNewFrame(OniFrame* pFrame) { (*m_newFrameCallback)(this, pFrame, m_newFrameCallbackCookie); } void raisePropertyChanged(int propertyId, const void* data, int dataSize) { (*m_propertyChangedCallback)(this, propertyId, data, dataSize, m_propertyChangedCookie); } StreamServices& getServices() { return *m_pServices; } private: StreamServices* m_pServices; NewFrameCallback m_newFrameCallback; void* m_newFrameCallbackCookie; PropertyChangedCallback m_propertyChangedCallback; void* m_propertyChangedCookie; }; class DeviceBase { public: DeviceBase() {} virtual ~DeviceBase() {} virtual OniStatus getSensorInfoList(OniSensorInfo** pSensorInfos, int* numSensors) = 0; virtual StreamBase* createStream(OniSensorType) = 0; virtual void destroyStream(StreamBase* pStream) = 0; virtual OniStatus setProperty(int /*propertyId*/, const void* /*data*/, int /*dataSize*/) {return ONI_STATUS_NOT_IMPLEMENTED;} virtual OniStatus getProperty(int /*propertyId*/, void* /*data*/, int* /*pDataSize*/) {return ONI_STATUS_NOT_IMPLEMENTED;} virtual OniBool isPropertySupported(int /*propertyId*/) {return FALSE;} virtual OniStatus invoke(int /*commandId*/, void* /*data*/, int /*dataSize*/) {return ONI_STATUS_NOT_IMPLEMENTED;} virtual OniBool isCommandSupported(int /*commandId*/) {return FALSE;} virtual OniStatus tryManualTrigger() {return ONI_STATUS_OK;} virtual void setPropertyChangedCallback(PropertyChangedCallback handler, void* pCookie) { m_propertyChangedCallback = handler; m_propertyChangedCookie = pCookie; } virtual void notifyAllProperties() { return; } virtual OniBool isImageRegistrationModeSupported(OniImageRegistrationMode mode) { return (mode == ONI_IMAGE_REGISTRATION_OFF); } protected: void raisePropertyChanged(int propertyId, const void* data, int dataSize) { (*m_propertyChangedCallback)(this, propertyId, data, dataSize, m_propertyChangedCookie); } private: PropertyChangedCallback m_propertyChangedCallback; void* m_propertyChangedCookie; }; class DriverServices { public: DriverServices(OniDriverServices* pDriverServices) : m_pDriverServices(pDriverServices) {} void errorLoggerAppend(const char* format, ...) { va_list args; va_start(args, format); m_pDriverServices->errorLoggerAppend(m_pDriverServices->driverServices, format, args); va_end(args); } void errorLoggerClear() { m_pDriverServices->errorLoggerClear(m_pDriverServices->driverServices); } void log(int severity, const char* file, int line, const char* mask, const char* message) { m_pDriverServices->log(m_pDriverServices->driverServices, severity, file, line, mask, message); } private: OniDriverServices* m_pDriverServices; }; class DriverBase { public: DriverBase(OniDriverServices* pDriverServices) : m_services(pDriverServices) {} virtual ~DriverBase() {} virtual OniStatus initialize(DeviceConnectedCallback connectedCallback, DeviceDisconnectedCallback disconnectedCallback, DeviceStateChangedCallback deviceStateChangedCallback, void* pCookie) { m_deviceConnectedEvent = connectedCallback; m_deviceDisconnectedEvent = disconnectedCallback; m_deviceStateChangedEvent = deviceStateChangedCallback; m_pCookie = pCookie; return ONI_STATUS_OK; } virtual DeviceBase* deviceOpen(const char* uri, const char* mode) = 0; virtual void deviceClose(DeviceBase* pDevice) = 0; virtual void shutdown() = 0; virtual OniStatus tryDevice(const char* /*uri*/) { return ONI_STATUS_ERROR;} virtual void* enableFrameSync(StreamBase** /*pStreams*/, int /*streamCount*/) { return NULL; } virtual void disableFrameSync(void* /*frameSyncGroup*/) {} protected: void deviceConnected(const OniDeviceInfo* pInfo) { (m_deviceConnectedEvent)(pInfo, m_pCookie); } void deviceDisconnected(const OniDeviceInfo* pInfo) { (m_deviceDisconnectedEvent)(pInfo, m_pCookie); } void deviceStateChanged(const OniDeviceInfo* pInfo, int errorState) { (m_deviceStateChangedEvent)(pInfo, errorState, m_pCookie); } DriverServices& getServices() { return m_services; } private: DeviceConnectedCallback m_deviceConnectedEvent; DeviceDisconnectedCallback m_deviceDisconnectedEvent; DeviceStateChangedCallback m_deviceStateChangedEvent; void* m_pCookie; DriverServices m_services; }; }} // oni::driver #define ONI_EXPORT_DRIVER(DriverClass) \ \ oni::driver::DriverBase* g_pDriver = NULL; \ \ /* As Driver */ \ ONI_C_API_EXPORT void oniDriverCreate(OniDriverServices* driverServices) { \ g_pDriver = XN_NEW(DriverClass, driverServices); \ } \ ONI_C_API_EXPORT void oniDriverDestroy() \ { \ g_pDriver->shutdown(); \ XN_DELETE(g_pDriver); g_pDriver = NULL; \ } \ ONI_C_API_EXPORT OniStatus oniDriverInitialize(oni::driver::DeviceConnectedCallback deviceConnectedCallback, \ oni::driver::DeviceDisconnectedCallback deviceDisconnectedCallback, \ oni::driver::DeviceStateChangedCallback deviceStateChangedCallback, \ void* pCookie) \ { \ return g_pDriver->initialize(deviceConnectedCallback, deviceDisconnectedCallback, deviceStateChangedCallback, pCookie); \ } \ \ ONI_C_API_EXPORT OniStatus oniDriverTryDevice(const char* uri) \ { \ return g_pDriver->tryDevice(uri); \ } \ \ /* As Device */ \ ONI_C_API_EXPORT oni::driver::DeviceBase* oniDriverDeviceOpen(const char* uri, const char* mode) \ { \ return g_pDriver->deviceOpen(uri, mode); \ } \ ONI_C_API_EXPORT void oniDriverDeviceClose(oni::driver::DeviceBase* pDevice) \ { \ g_pDriver->deviceClose(pDevice); \ } \ \ ONI_C_API_EXPORT OniStatus oniDriverDeviceGetSensorInfoList(oni::driver::DeviceBase* pDevice, OniSensorInfo** pSensorInfos, \ int* numSensors) \ { \ return pDevice->getSensorInfoList(pSensorInfos, numSensors); \ } \ \ ONI_C_API_EXPORT oni::driver::StreamBase* oniDriverDeviceCreateStream(oni::driver::DeviceBase* pDevice, \ OniSensorType sensorType) \ { \ return pDevice->createStream(sensorType); \ } \ \ ONI_C_API_EXPORT void oniDriverDeviceDestroyStream(oni::driver::DeviceBase* pDevice, oni::driver::StreamBase* pStream) \ { \ return pDevice->destroyStream(pStream); \ } \ \ ONI_C_API_EXPORT OniStatus oniDriverDeviceSetProperty(oni::driver::DeviceBase* pDevice, int propertyId, \ const void* data, int dataSize) \ { \ return pDevice->setProperty(propertyId, data, dataSize); \ } \ ONI_C_API_EXPORT OniStatus oniDriverDeviceGetProperty(oni::driver::DeviceBase* pDevice, int propertyId, \ void* data, int* pDataSize) \ { \ return pDevice->getProperty(propertyId, data, pDataSize); \ } \ ONI_C_API_EXPORT OniBool oniDriverDeviceIsPropertySupported(oni::driver::DeviceBase* pDevice, int propertyId) \ { \ return pDevice->isPropertySupported(propertyId); \ } \ ONI_C_API_EXPORT void oniDriverDeviceSetPropertyChangedCallback(oni::driver::DeviceBase* pDevice, \ oni::driver::PropertyChangedCallback handler, void* pCookie) \ { \ pDevice->setPropertyChangedCallback(handler, pCookie); \ } \ ONI_C_API_EXPORT void oniDriverDeviceNotifyAllProperties(oni::driver::DeviceBase* pDevice) \ { \ pDevice->notifyAllProperties(); \ } \ ONI_C_API_EXPORT OniStatus oniDriverDeviceInvoke(oni::driver::DeviceBase* pDevice, int commandId, \ void* data, int dataSize) \ { \ return pDevice->invoke(commandId, data, dataSize); \ } \ ONI_C_API_EXPORT OniBool oniDriverDeviceIsCommandSupported(oni::driver::DeviceBase* pDevice, int commandId) \ { \ return pDevice->isCommandSupported(commandId); \ } \ ONI_C_API_EXPORT OniStatus oniDriverDeviceTryManualTrigger(oni::driver::DeviceBase* pDevice) \ { \ return pDevice->tryManualTrigger(); \ } \ ONI_C_API_EXPORT OniBool oniDriverDeviceIsImageRegistrationModeSupported(oni::driver::DeviceBase* pDevice, \ OniImageRegistrationMode mode) \ { \ return pDevice->isImageRegistrationModeSupported(mode); \ } \ \ /* As Stream */ \ ONI_C_API_EXPORT void oniDriverStreamSetServices(oni::driver::StreamBase* pStream, OniStreamServices* pServices) \ { \ pStream->setServices((oni::driver::StreamServices*)pServices); \ } \ \ ONI_C_API_EXPORT OniStatus oniDriverStreamSetProperty(oni::driver::StreamBase* pStream, int propertyId, \ const void* data, int dataSize) \ { \ return pStream->setProperty(propertyId, data, dataSize); \ } \ ONI_C_API_EXPORT OniStatus oniDriverStreamGetProperty(oni::driver::StreamBase* pStream, int propertyId, void* data, \ int* pDataSize) \ { \ return pStream->getProperty(propertyId, data, pDataSize); \ } \ ONI_C_API_EXPORT OniBool oniDriverStreamIsPropertySupported(oni::driver::StreamBase* pStream, int propertyId) \ { \ return pStream->isPropertySupported(propertyId); \ } \ ONI_C_API_EXPORT void oniDriverStreamSetPropertyChangedCallback(oni::driver::StreamBase* pStream, \ oni::driver::PropertyChangedCallback handler, void* pCookie) \ { \ pStream->setPropertyChangedCallback(handler, pCookie); \ } \ ONI_C_API_EXPORT void oniDriverStreamNotifyAllProperties(oni::driver::StreamBase* pStream) \ { \ pStream->notifyAllProperties(); \ } \ ONI_C_API_EXPORT OniStatus oniDriverStreamInvoke(oni::driver::StreamBase* pStream, int commandId, \ void* data, int dataSize) \ { \ return pStream->invoke(commandId, data, dataSize); \ } \ ONI_C_API_EXPORT OniBool oniDriverStreamIsCommandSupported(oni::driver::StreamBase* pStream, int commandId) \ { \ return pStream->isCommandSupported(commandId); \ } \ \ ONI_C_API_EXPORT OniStatus oniDriverStreamStart(oni::driver::StreamBase* pStream) \ { \ return pStream->start(); \ } \ ONI_C_API_EXPORT void oniDriverStreamStop(oni::driver::StreamBase* pStream) \ { \ pStream->stop(); \ } \ \ ONI_C_API_EXPORT int oniDriverStreamGetRequiredFrameSize(oni::driver::StreamBase* pStream) \ { \ return pStream->getRequiredFrameSize(); \ } \ \ ONI_C_API_EXPORT void oniDriverStreamSetNewFrameCallback(oni::driver::StreamBase* pStream, \ oni::driver::NewFrameCallback handler, void* pCookie) \ { \ pStream->setNewFrameCallback(handler, pCookie); \ } \ \ ONI_C_API_EXPORT OniStatus oniDriverStreamConvertDepthToColorCoordinates(oni::driver::StreamBase* pDepthStream, \ oni::driver::StreamBase* pColorStream, int depthX, int depthY, OniDepthPixel depthZ, int* pColorX, int* pColorY) \ { \ return pDepthStream->convertDepthToColorCoordinates(pColorStream, depthX, depthY, depthZ, pColorX, pColorY); \ } \ \ ONI_C_API_EXPORT void* oniDriverEnableFrameSync(oni::driver::StreamBase** pStreams, int streamCount) \ { \ return g_pDriver->enableFrameSync(pStreams, streamCount); \ } \ \ ONI_C_API_EXPORT void oniDriverDisableFrameSync(void* frameSyncGroup) \ { \ return g_pDriver->disableFrameSync(frameSyncGroup); \ } \ #endif // _ONI_DRIVER_API_H_ OniDriverTypes.h000066400000000000000000000051271264163024100330140ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Driver/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_DRIVER_TYPES_H_ #define _ONI_DRIVER_TYPES_H_ #include #include #define ONI_STREAM_PROPERTY_PRIVATE_BASE XN_MAX_UINT16 typedef struct { int dataSize; void* data; } OniGeneralBuffer; /////// DriverServices struct OniDriverServices { void* driverServices; void (ONI_CALLBACK_TYPE* errorLoggerAppend)(void* driverServices, const char* format, va_list args); void (ONI_CALLBACK_TYPE* errorLoggerClear)(void* driverServices); void (ONI_CALLBACK_TYPE* log)(void* driverServices, int severity, const char* file, int line, const char* mask, const char* message); }; struct OniStreamServices { void* streamServices; int (ONI_CALLBACK_TYPE* getDefaultRequiredFrameSize)(void* streamServices); OniFrame* (ONI_CALLBACK_TYPE* acquireFrame)(void* streamServices); // returns a frame with size corresponding to getRequiredFrameSize() void (ONI_CALLBACK_TYPE* addFrameRef)(void* streamServices, OniFrame* pframe); void (ONI_CALLBACK_TYPE* releaseFrame)(void* streamServices, OniFrame* pframe); }; #endif // _ONI_DRIVER_TYPES_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Linux-Arm/000077500000000000000000000000001264163024100303505ustar00rootroot00000000000000OniPlatformLinux-Arm.h000066400000000000000000000040741264163024100344360ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Linux-Arm/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PLATFORM_LINUX_ARM_H_ #define _ONI_PLATFORM_LINUX_ARM_H_ // Start with Linux-x86, and override what's different #include "../Linux-x86/OniPlatformLinux-x86.h" //--------------------------------------------------------------------------- // Platform Basic Definition //--------------------------------------------------------------------------- #undef ONI_PLATFORM #undef ONI_PLATFORM_STRING #define ONI_PLATFORM ONI_PLATFORM_LINUX_ARM #define ONI_PLATFORM_STRING "Linux-Arm" #endif //_ONI_PLATFORM_LINUX_ARM_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Linux-x86/000077500000000000000000000000001264163024100302565ustar00rootroot00000000000000OniPlatformLinux-x86.h000066400000000000000000000107401264163024100342470ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Linux-x86/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PLATFORM_LINUX_X86_H_ #define _ONI_PLATFORM_LINUX_X86_H_ //--------------------------------------------------------------------------- // Prerequisites //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Includes //--------------------------------------------------------------------------- #include #include #include #include #include #include #include //--------------------------------------------------------------------------- // Platform Basic Definition //--------------------------------------------------------------------------- #define ONI_PLATFORM ONI_PLATFORM_LINUX_X86 #define ONI_PLATFORM_STRING "Linux-x86" //--------------------------------------------------------------------------- // Platform Capabilities //--------------------------------------------------------------------------- #define ONI_PLATFORM_ENDIAN_TYPE ONI_PLATFORM_IS_LITTLE_ENDIAN #define ONI_PLATFORM_SUPPORTS_DYNAMIC_LIBS 1 //--------------------------------------------------------------------------- // Memory //--------------------------------------------------------------------------- /** The default memory alignment. */ #define ONI_DEFAULT_MEM_ALIGN 16 /** The thread static declarator (using TLS). */ #define ONI_THREAD_STATIC __thread //--------------------------------------------------------------------------- // Files //--------------------------------------------------------------------------- /** The maximum allowed file path size (in bytes). */ #define ONI_FILE_MAX_PATH 256 //--------------------------------------------------------------------------- // Call back //--------------------------------------------------------------------------- /** The std call type. */ #define ONI_STDCALL __stdcall /** The call back calling convention. */ #define ONI_CALLBACK_TYPE /** The C and C++ calling convension. */ #define ONI_C_DECL //--------------------------------------------------------------------------- // Macros //--------------------------------------------------------------------------- /** Returns the date and time at compile time. */ #define ONI_TIMESTAMP __DATE__ " " __TIME__ /** Converts n into a pre-processor string. */ #define ONI_STRINGIFY(n) ONI_STRINGIFY_HELPER(n) #define ONI_STRINGIFY_HELPER(n) #n //--------------------------------------------------------------------------- // API Export/Import Macros //--------------------------------------------------------------------------- /** Indicates an exported shared library function. */ #define ONI_API_EXPORT __attribute__ ((visibility("default"))) /** Indicates an imported shared library function. */ #define ONI_API_IMPORT /** Indicates a deprecated function */ #define ONI_API_DEPRECATED(msg) __attribute__((warning("This function is deprecated: " msg))) #endif //_ONI_PLATFORM_LINUX_X86_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/MacOSX/000077500000000000000000000000001264163024100276265ustar00rootroot00000000000000OniPlatformMacOSX.h000066400000000000000000000041401264163024100331640ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/MacOSX/***************************************************************************** * * * PrimeSense PSCommon Library * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of PSCommon. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PLATFORM_MACOSX_H_ #define _ONI_PLATFORM_MACOSX_H_ // Start with Linux-x86, and override what's different #include "../Linux-x86/OniPlatformLinux-x86.h" #include #undef ONI_PLATFORM #undef ONI_PLATFORM_STRING #define ONI_PLATFORM ONI_PLATFORM_MACOSX #define ONI_PLATFORM_STRING "MacOSX" #define ONI_PLATFORM_HAS_NO_TIMED_OPS #define ONI_PLATFORM_HAS_NO_CLOCK_GETTIME #define ONI_PLATFORM_HAS_NO_SCHED_PARAM #define ONI_PLATFORM_HAS_BUILTIN_SEMUN #undef ONI_THREAD_STATIC #define ONI_THREAD_STATIC #endif //_ONI_PLATFORM_MACOSX_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniCAPI.h000066400000000000000000000315471264163024100301010ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_C_API_H_ #define _ONI_C_API_H_ #include "OniPlatform.h" #include "OniCTypes.h" #include "OniCProperties.h" #include "OniVersion.h" /******************************************** General APIs */ /** Initialize OpenNI2. Use ONI_API_VERSION as the version. */ ONI_C_API OniStatus oniInitialize(int apiVersion); /** Shutdown OpenNI2 */ ONI_C_API void oniShutdown(); /** * Get the list of currently connected device. * Each device is represented by its OniDeviceInfo. * pDevices will be allocated inside. */ ONI_C_API OniStatus oniGetDeviceList(OniDeviceInfo** pDevices, int* pNumDevices); /** Release previously allocated device list */ ONI_C_API OniStatus oniReleaseDeviceList(OniDeviceInfo* pDevices); ONI_C_API OniStatus oniRegisterDeviceCallbacks(OniDeviceCallbacks* pCallbacks, void* pCookie, OniCallbackHandle* pHandle); ONI_C_API void oniUnregisterDeviceCallbacks(OniCallbackHandle handle); /** Wait for any of the streams to have a new frame */ ONI_C_API OniStatus oniWaitForAnyStream(OniStreamHandle* pStreams, int numStreams, int* pStreamIndex, int timeout); /** Get the current version of OpenNI2 */ ONI_C_API OniVersion oniGetVersion(); /** Translate from format to number of bytes per pixel. Will return 0 for formats in which the number of bytes per pixel isn't fixed. */ ONI_C_API int oniFormatBytesPerPixel(OniPixelFormat format); /** Get internal error */ ONI_C_API const char* oniGetExtendedError(); /******************************************** Device APIs */ /** Open a device. Uri can be taken from the matching OniDeviceInfo. */ ONI_C_API OniStatus oniDeviceOpen(const char* uri, OniDeviceHandle* pDevice); /** Close a device */ ONI_C_API OniStatus oniDeviceClose(OniDeviceHandle device); /** Get the possible configurations available for a specific source, or NULL if the source does not exist. */ ONI_C_API const OniSensorInfo* oniDeviceGetSensorInfo(OniDeviceHandle device, OniSensorType sensorType); /** Get the OniDeviceInfo of a certain device. */ ONI_C_API OniStatus oniDeviceGetInfo(OniDeviceHandle device, OniDeviceInfo* pInfo); /** Create a new stream in the device. The stream will originate from the source. */ ONI_C_API OniStatus oniDeviceCreateStream(OniDeviceHandle device, OniSensorType sensorType, OniStreamHandle* pStream); ONI_C_API OniStatus oniDeviceEnableDepthColorSync(OniDeviceHandle device); ONI_C_API void oniDeviceDisableDepthColorSync(OniDeviceHandle device); ONI_C_API OniBool oniDeviceGetDepthColorSyncEnabled(OniDeviceHandle device); /** Set property in the device. Use the properties listed in OniTypes.h: ONI_DEVICE_PROPERTY_..., or specific ones supplied by the device. */ ONI_C_API OniStatus oniDeviceSetProperty(OniDeviceHandle device, int propertyId, const void* data, int dataSize); /** Get property in the device. Use the properties listed in OniTypes.h: ONI_DEVICE_PROPERTY_..., or specific ones supplied by the device. */ ONI_C_API OniStatus oniDeviceGetProperty(OniDeviceHandle device, int propertyId, void* data, int* pDataSize); /** Check if the property is supported by the device. Use the properties listed in OniTypes.h: ONI_DEVICE_PROPERTY_..., or specific ones supplied by the device. */ ONI_C_API OniBool oniDeviceIsPropertySupported(OniDeviceHandle device, int propertyId); /** Invoke an internal functionality of the device. */ ONI_C_API OniStatus oniDeviceInvoke(OniDeviceHandle device, int commandId, void* data, int dataSize); /** Check if a command is supported, for invoke */ ONI_C_API OniBool oniDeviceIsCommandSupported(OniDeviceHandle device, int commandId); ONI_C_API OniBool oniDeviceIsImageRegistrationModeSupported(OniDeviceHandle device, OniImageRegistrationMode mode); /** @internal */ ONI_C_API OniStatus oniDeviceOpenEx(const char* uri, const char* mode, OniDeviceHandle* pDevice); /******************************************** Stream APIs */ /** Destroy an existing stream */ ONI_C_API void oniStreamDestroy(OniStreamHandle stream); /** Get the OniSensorInfo of the certain stream. */ ONI_C_API const OniSensorInfo* oniStreamGetSensorInfo(OniStreamHandle stream); /** Start generating data from the stream. */ ONI_C_API OniStatus oniStreamStart(OniStreamHandle stream); /** Stop generating data from the stream. */ ONI_C_API void oniStreamStop(OniStreamHandle stream); /** Get the next frame from the stream. This function is blocking until there is a new frame from the stream. For timeout, use oniWaitForStreams() first */ ONI_C_API OniStatus oniStreamReadFrame(OniStreamHandle stream, OniFrame** pFrame); /** Register a callback to when the stream has a new frame. */ ONI_C_API OniStatus oniStreamRegisterNewFrameCallback(OniStreamHandle stream, OniNewFrameCallback handler, void* pCookie, OniCallbackHandle* pHandle); /** Unregister a previously registered callback to when the stream has a new frame. */ ONI_C_API void oniStreamUnregisterNewFrameCallback(OniStreamHandle stream, OniCallbackHandle handle); /** Set property in the stream. Use the properties listed in OniTypes.h: ONI_STREAM_PROPERTY_..., or specific ones supplied by the device for its streams. */ ONI_C_API OniStatus oniStreamSetProperty(OniStreamHandle stream, int propertyId, const void* data, int dataSize); /** Get property in the stream. Use the properties listed in OniTypes.h: ONI_STREAM_PROPERTY_..., or specific ones supplied by the device for its streams. */ ONI_C_API OniStatus oniStreamGetProperty(OniStreamHandle stream, int propertyId, void* data, int* pDataSize); /** Check if the property is supported the stream. Use the properties listed in OniTypes.h: ONI_STREAM_PROPERTY_..., or specific ones supplied by the device for its streams. */ ONI_C_API OniBool oniStreamIsPropertySupported(OniStreamHandle stream, int propertyId); /** Invoke an internal functionality of the stream. */ ONI_C_API OniStatus oniStreamInvoke(OniStreamHandle stream, int commandId, void* data, int dataSize); /** Check if a command is supported, for invoke */ ONI_C_API OniBool oniStreamIsCommandSupported(OniStreamHandle stream, int commandId); /** Sets the stream buffer allocation functions. Note that this function may only be called while stream is not started. */ ONI_C_API OniStatus oniStreamSetFrameBuffersAllocator(OniStreamHandle stream, OniFrameAllocBufferCallback alloc, OniFrameFreeBufferCallback free, void* pCookie); //// /** Mark another user of the frame. */ ONI_C_API void oniFrameAddRef(OniFrame* pFrame); /** Mark that the frame is no longer needed. */ ONI_C_API void oniFrameRelease(OniFrame* pFrame); // ONI_C_API OniStatus oniConvertRealWorldToProjective(OniStreamHandle stream, OniFloatPoint3D* pRealWorldPoint, OniFloatPoint3D* pProjectivePoint); // ONI_C_API OniStatus oniConvertProjectiveToRealWorld(OniStreamHandle stream, OniFloatPoint3D* pProjectivePoint, OniFloatPoint3D* pRealWorldPoint); /** * Creates a recorder that records to a file. * @param [in] fileName The name of the file that will contain the recording. * @param [out] pRecorder Points to the handle to the newly created recorder. * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniCreateRecorder(const char* fileName, OniRecorderHandle* pRecorder); /** * Attaches a stream to a recorder. The amount of attached streams is virtually * infinite. You cannot attach a stream after you have started a recording, if * you do: an error will be returned by oniRecorderAttachStream. * @param [in] recorder The handle to the recorder. * @param [in] stream The handle to the stream. * @param [in] allowLossyCompression Allows/denies lossy compression * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniRecorderAttachStream( OniRecorderHandle recorder, OniStreamHandle stream, OniBool allowLossyCompression); /** * Starts recording. There must be at least one stream attached to the recorder, * if not: oniRecorderStart will return an error. * @param[in] recorder The handle to the recorder. * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniRecorderStart(OniRecorderHandle recorder); /** * Stops recording. You can resume recording via oniRecorderStart. * @param[in] recorder The handle to the recorder. * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API void oniRecorderStop(OniRecorderHandle recorder); /** * Stops recording if needed, and destroys a recorder. * @param [in,out] recorder The handle to the recorder, the handle will be * invalidated (nullified) when the function returns. * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniRecorderDestroy(OniRecorderHandle* pRecorder); ONI_C_API OniStatus oniCoordinateConverterDepthToWorld(OniStreamHandle depthStream, float depthX, float depthY, float depthZ, float* pWorldX, float* pWorldY, float* pWorldZ); ONI_C_API OniStatus oniCoordinateConverterWorldToDepth(OniStreamHandle depthStream, float worldX, float worldY, float worldZ, float* pDepthX, float* pDepthY, float* pDepthZ); ONI_C_API OniStatus oniCoordinateConverterDepthToColor(OniStreamHandle depthStream, OniStreamHandle colorStream, int depthX, int depthY, OniDepthPixel depthZ, int* pColorX, int* pColorY); /******************************************** Log APIs */ /** * Change the log output folder * @param const char * strOutputFolder [in] path to the desirebale folder * * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniSetLogOutputFolder(const char* strOutputFolder); /** * Get the current log file name * @param char * strFileName [out] hold the returned file name * @param int nBufferSize [in] size of strFileName * * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniGetLogFileName(char* strFileName, int nBufferSize); /** * Set the Minimum severity for log produce * @param const char * strMask [in] Name of the logger * * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniSetLogMinSeverity(int nMinSeverity); /** * Configures if log entries will be printed to console. * @param OniBool bConsoleOutput [in] TRUE to print log entries to console, FALSE otherwise. * * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniSetLogConsoleOutput(OniBool bConsoleOutput); /** * Configures if log entries will be printed to a log file. * @param OniBool bFileOutput [in] TRUE to print log entries to the file, FALSE otherwise. * * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniSetLogFileOutput(OniBool bFileOutput); #if ONI_PLATFORM == ONI_PLATFORM_ANDROID_ARM /** * Configures if log entries will be printed to the Android log. * @param OniBool bAndroidOutput [in] TRUE to print log entries to the Android log, FALSE otherwise. * * @retval ONI_STATUS_OK Upon successful completion. * @retval ONI_STATUS_ERROR Upon any kind of failure. */ ONI_C_API OniStatus oniSetLogAndroidOutput(OniBool bAndroidOutput); #endif #endif // _ONI_C_API_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniCEnums.h000066400000000000000000000054411264163024100305510ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_C_ENUMS_H_ #define _ONI_C_ENUMS_H_ /** Possible failure values */ typedef enum { ONI_STATUS_OK = 0, ONI_STATUS_ERROR = 1, ONI_STATUS_NOT_IMPLEMENTED = 2, ONI_STATUS_NOT_SUPPORTED = 3, ONI_STATUS_BAD_PARAMETER = 4, ONI_STATUS_OUT_OF_FLOW = 5, ONI_STATUS_NO_DEVICE = 6, ONI_STATUS_TIME_OUT = 102, } OniStatus; /** The source of the stream */ typedef enum { ONI_SENSOR_IR = 1, ONI_SENSOR_COLOR = 2, ONI_SENSOR_DEPTH = 3, } OniSensorType; /** All available formats of the output of a stream */ typedef enum { // Depth ONI_PIXEL_FORMAT_DEPTH_1_MM = 100, ONI_PIXEL_FORMAT_DEPTH_100_UM = 101, ONI_PIXEL_FORMAT_SHIFT_9_2 = 102, ONI_PIXEL_FORMAT_SHIFT_9_3 = 103, // Color ONI_PIXEL_FORMAT_RGB888 = 200, ONI_PIXEL_FORMAT_YUV422 = 201, ONI_PIXEL_FORMAT_GRAY8 = 202, ONI_PIXEL_FORMAT_GRAY16 = 203, ONI_PIXEL_FORMAT_JPEG = 204, ONI_PIXEL_FORMAT_YUYV = 205, } OniPixelFormat; typedef enum { ONI_DEVICE_STATE_OK = 0, ONI_DEVICE_STATE_ERROR = 1, ONI_DEVICE_STATE_NOT_READY = 2, ONI_DEVICE_STATE_EOF = 3 } OniDeviceState; typedef enum { ONI_IMAGE_REGISTRATION_OFF = 0, ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR = 1, } OniImageRegistrationMode; enum { ONI_TIMEOUT_NONE = 0, ONI_TIMEOUT_FOREVER = -1, }; #endif // _ONI_C_ENUMS_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniCProperties.h000066400000000000000000000056341264163024100316220ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_C_PROPERTIES_H_ #define _ONI_C_PROPERTIES_H_ // Device properties enum { ONI_DEVICE_PROPERTY_FIRMWARE_VERSION = 0, // By implementation ONI_DEVICE_PROPERTY_DRIVER_VERSION = 1, // OniVersion ONI_DEVICE_PROPERTY_HARDWARE_VERSION = 2, // int ONI_DEVICE_PROPERTY_SERIAL_NUMBER = 3, // string ONI_DEVICE_PROPERTY_ERROR_STATE = 4, // ?? ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION = 5, // OniImageRegistrationMode // Files ONI_DEVICE_PROPERTY_PLAYBACK_SPEED = 100, // float ONI_DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED = 101, // OniBool }; // Stream properties enum { ONI_STREAM_PROPERTY_CROPPING = 0, // OniCropping* ONI_STREAM_PROPERTY_HORIZONTAL_FOV = 1, // float: radians ONI_STREAM_PROPERTY_VERTICAL_FOV = 2, // float: radians ONI_STREAM_PROPERTY_VIDEO_MODE = 3, // OniVideoMode* ONI_STREAM_PROPERTY_MAX_VALUE = 4, // int ONI_STREAM_PROPERTY_MIN_VALUE = 5, // int ONI_STREAM_PROPERTY_STRIDE = 6, // int ONI_STREAM_PROPERTY_MIRRORING = 7, // OniBool ONI_STREAM_PROPERTY_NUMBER_OF_FRAMES = 8, // int // Camera ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE = 100, // OniBool ONI_STREAM_PROPERTY_AUTO_EXPOSURE = 101, // OniBool ONI_STREAM_PROPERTY_EXPOSURE = 102, // int ONI_STREAM_PROPERTY_GAIN = 103, // int }; // Device commands (for Invoke) enum { ONI_DEVICE_COMMAND_SEEK = 1, // OniSeek }; #endif // _ONI_C_PROPERTIES_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniCTypes.h000066400000000000000000000130421264163024100305620ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_TYPES_H_ #define _ONI_TYPES_H_ #include "OniPlatform.h" #include "OniCEnums.h" /** Basic types **/ typedef int OniBool; #ifndef TRUE #define TRUE 1 #endif //TRUE #ifndef FALSE #define FALSE 0 #endif //FALSE #define ONI_MAX_STR 256 #define ONI_MAX_SENSORS 10 struct OniCallbackHandleImpl; typedef struct OniCallbackHandleImpl* OniCallbackHandle; /** Holds an OpenNI version number, which consists of four separate numbers in the format: @c major.minor.maintenance.build. For example: 2.0.0.20. */ typedef struct { /** Major version number, incremented for major API restructuring. */ int major; /** Minor version number, incremented when significant new features added. */ int minor; /** Maintenance build number, incremented for new releases that primarily provide minor bug fixes. */ int maintenance; /** Build number. Incremented for each new API build. Generally not shown on the installer and download site. */ int build; } OniVersion; typedef int OniHardwareVersion; /** Description of the output: format and resolution */ typedef struct { OniPixelFormat pixelFormat; int resolutionX; int resolutionY; int fps; } OniVideoMode; /** List of supported video modes by a specific source */ typedef struct { OniSensorType sensorType; int numSupportedVideoModes; OniVideoMode *pSupportedVideoModes; } OniSensorInfo; /** Basic description of a device */ typedef struct { char uri[ONI_MAX_STR]; char vendor[ONI_MAX_STR]; char name[ONI_MAX_STR]; uint16_t usbVendorId; uint16_t usbProductId; } OniDeviceInfo; struct _OniDevice; typedef _OniDevice* OniDeviceHandle; struct _OniStream; typedef _OniStream* OniStreamHandle; struct _OniRecorder; typedef _OniRecorder* OniRecorderHandle; /** All information of the current frame */ typedef struct { int dataSize; void* data; OniSensorType sensorType; uint64_t timestamp; int frameIndex; int width; int height; OniVideoMode videoMode; OniBool croppingEnabled; int cropOriginX; int cropOriginY; int stride; } OniFrame; typedef void (ONI_CALLBACK_TYPE* OniNewFrameCallback)(OniStreamHandle stream, void* pCookie); typedef void (ONI_CALLBACK_TYPE* OniGeneralCallback)(void* pCookie); typedef void (ONI_CALLBACK_TYPE* OniDeviceInfoCallback)(const OniDeviceInfo* pInfo, void* pCookie); typedef void (ONI_CALLBACK_TYPE* OniDeviceStateCallback)(const OniDeviceInfo* pInfo, OniDeviceState deviceState, void* pCookie); typedef void* (ONI_CALLBACK_TYPE* OniFrameAllocBufferCallback)(int size, void* pCookie); typedef void (ONI_CALLBACK_TYPE* OniFrameFreeBufferCallback)(void* data, void* pCookie); typedef struct { OniDeviceInfoCallback deviceConnected; OniDeviceInfoCallback deviceDisconnected; OniDeviceStateCallback deviceStateChanged; } OniDeviceCallbacks; typedef struct { int enabled; int originX; int originY; int width; int height; } OniCropping; // Pixel types /** Pixel type used to store depth images. */ typedef uint16_t OniDepthPixel; /** Pixel type used to store 16-bit grayscale images */ typedef uint16_t OniGrayscale16Pixel; /** Pixel type used to store 8-bit grayscale/bayer images */ typedef uint8_t OniGrayscale8Pixel; #pragma pack (push, 1) /** Holds the value of a single color image pixel in 24-bit RGB format. */ typedef struct { /* Red value of this pixel. */ uint8_t r; /* Green value of this pixel. */ uint8_t g; /* Blue value of this pixel. */ uint8_t b; } OniRGB888Pixel; /** Holds the value of two pixels in YUV422 format (Luminance/Chrominance,16-bits/pixel). The first pixel has the values y1, u, v. The second pixel has the values y2, u, v. */ typedef struct { /** First chrominance value for two pixels, stored as blue luminance difference signal. */ uint8_t u; /** Overall luminance value of first pixel. */ uint8_t y1; /** Second chrominance value for two pixels, stored as red luminance difference signal. */ uint8_t v; /** Overall luminance value of second pixel. */ uint8_t y2; } OniYUV422DoublePixel; #pragma pack (pop) typedef struct { int frameIndex; OniStreamHandle stream; } OniSeek; #endif // _ONI_TYPES_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniEnums.h000066400000000000000000000053271264163024100304510ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_ENUMS_H_ #define _ONI_ENUMS_H_ namespace openni { /** Possible failure values */ typedef enum { STATUS_OK = 0, STATUS_ERROR = 1, STATUS_NOT_IMPLEMENTED = 2, STATUS_NOT_SUPPORTED = 3, STATUS_BAD_PARAMETER = 4, STATUS_OUT_OF_FLOW = 5, STATUS_NO_DEVICE = 6, STATUS_TIME_OUT = 102, } Status; /** The source of the stream */ typedef enum { SENSOR_IR = 1, SENSOR_COLOR = 2, SENSOR_DEPTH = 3, } SensorType; /** All available formats of the output of a stream */ typedef enum { // Depth PIXEL_FORMAT_DEPTH_1_MM = 100, PIXEL_FORMAT_DEPTH_100_UM = 101, PIXEL_FORMAT_SHIFT_9_2 = 102, PIXEL_FORMAT_SHIFT_9_3 = 103, // Color PIXEL_FORMAT_RGB888 = 200, PIXEL_FORMAT_YUV422 = 201, PIXEL_FORMAT_GRAY8 = 202, PIXEL_FORMAT_GRAY16 = 203, PIXEL_FORMAT_JPEG = 204, PIXEL_FORMAT_YUYV = 205, } PixelFormat; typedef enum { DEVICE_STATE_OK = 0, DEVICE_STATE_ERROR = 1, DEVICE_STATE_NOT_READY = 2, DEVICE_STATE_EOF = 3 } DeviceState; typedef enum { IMAGE_REGISTRATION_OFF = 0, IMAGE_REGISTRATION_DEPTH_TO_COLOR = 1, } ImageRegistrationMode; static const int TIMEOUT_NONE = 0; static const int TIMEOUT_FOREVER = -1; } // namespace openni #endif // _ONI_ENUMS_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniPlatform.h000066400000000000000000000060301264163024100311360ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PLATFORM_H_ #define _ONI_PLATFORM_H_ // Supported platforms #define ONI_PLATFORM_WIN32 1 #define ONI_PLATFORM_LINUX_X86 2 #define ONI_PLATFORM_LINUX_ARM 3 #define ONI_PLATFORM_MACOSX 4 #define ONI_PLATFORM_ANDROID_ARM 5 #if (defined _WIN32) # ifndef RC_INVOKED # if _MSC_VER < 1300 # error OpenNI Platform Abstraction Layer - Win32 - Microsoft Visual Studio version below 2003 (7.0) are not supported! # endif # endif # include "Win32/OniPlatformWin32.h" #elif defined (ANDROID) && defined (__arm__) # include "Android-Arm/OniPlatformAndroid-Arm.h" #elif (__linux__ && (__i386__ || __x86_64__)) # include "Linux-x86/OniPlatformLinux-x86.h" #elif (__linux__ && __arm__) # include "Linux-Arm/OniPlatformLinux-Arm.h" #elif _ARC # include "ARC/OniPlaformARC.h" #elif (__APPLE__) # include "MacOSX/OniPlatformMacOSX.h" #else # error Xiron Platform Abstraction Layer - Unsupported Platform! #endif #ifdef __cplusplus # define ONI_C extern "C" # define ONI_C_API_EXPORT ONI_C ONI_API_EXPORT # define ONI_C_API_IMPORT ONI_C ONI_API_IMPORT # define ONI_CPP_API_EXPORT ONI_API_EXPORT # define ONI_CPP_API_IMPORT ONI_API_IMPORT #else // __cplusplus # define ONI_C_API_EXPORT ONI_API_EXPORT # define ONI_C_API_IMPORT ONI_API_IMPORT #endif // __cplusplus #ifdef OPENNI2_EXPORT # define ONI_C_API ONI_C_API_EXPORT # define ONI_CPP_API ONI_CPP_API_EXPORT #else // OPENNI2_EXPORT # define ONI_C_API ONI_C_API_IMPORT # define ONI_CPP_API ONI_CPP_API_IMPORT #endif // OPENNI2_EXPORT #endif // _ONI_PLATFORM_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniProperties.h000066400000000000000000000055431264163024100315160ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PROPERTIES_H_ #define _ONI_PROPERTIES_H_ namespace openni { // Device properties enum { DEVICE_PROPERTY_FIRMWARE_VERSION = 0, // string DEVICE_PROPERTY_DRIVER_VERSION = 1, // OniVersion DEVICE_PROPERTY_HARDWARE_VERSION = 2, // int DEVICE_PROPERTY_SERIAL_NUMBER = 3, // string DEVICE_PROPERTY_ERROR_STATE = 4, // ?? DEVICE_PROPERTY_IMAGE_REGISTRATION = 5, // OniImageRegistrationMode // Files DEVICE_PROPERTY_PLAYBACK_SPEED = 100, // float DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED = 101, // OniBool }; // Stream properties enum { STREAM_PROPERTY_CROPPING = 0, // OniCropping* STREAM_PROPERTY_HORIZONTAL_FOV = 1, // float: radians STREAM_PROPERTY_VERTICAL_FOV = 2, // float: radians STREAM_PROPERTY_VIDEO_MODE = 3, // OniVideoMode* STREAM_PROPERTY_MAX_VALUE = 4, // int STREAM_PROPERTY_MIN_VALUE = 5, // int STREAM_PROPERTY_STRIDE = 6, // int STREAM_PROPERTY_MIRRORING = 7, // OniBool STREAM_PROPERTY_NUMBER_OF_FRAMES = 8, // int // Camera STREAM_PROPERTY_AUTO_WHITE_BALANCE = 100, // OniBool STREAM_PROPERTY_AUTO_EXPOSURE = 101, // OniBool STREAM_PROPERTY_EXPOSURE = 102, // int STREAM_PROPERTY_GAIN = 103, // int }; // Device commands (for Invoke) enum { DEVICE_COMMAND_SEEK = 1, // OniSeek }; } // namespace openni #endif // _ONI_PROPERTIES_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OniVersion.h000066400000000000000000000052001264163024100307750ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #include "OniPlatform.h" #define ONI_VERSION_MAJOR 2 #define ONI_VERSION_MINOR 2 #define ONI_VERSION_MAINTENANCE 0 #define ONI_VERSION_BUILD 33 /** OpenNI version (in brief string format): "Major.Minor.Maintenance (Build)" */ #define ONI_BRIEF_VERSION_STRING \ ONI_STRINGIFY(ONI_VERSION_MAJOR) "." \ ONI_STRINGIFY(ONI_VERSION_MINOR) "." \ ONI_STRINGIFY(ONI_VERSION_MAINTENANCE) \ " (Build " ONI_STRINGIFY(ONI_VERSION_BUILD) ")" /** OpenNI version (in numeric format): (OpenNI major version * 100000000 + OpenNI minor version * 1000000 + OpenNI maintenance version * 10000 + OpenNI build version). */ #define ONI_VERSION (ONI_VERSION_MAJOR*100000000 + ONI_VERSION_MINOR*1000000 + ONI_VERSION_MAINTENANCE*10000 + ONI_VERSION_BUILD) #define ONI_CREATE_API_VERSION(major, minor) ((major)*1000 + (minor)) #define ONI_API_VERSION ONI_CREATE_API_VERSION(ONI_VERSION_MAJOR, ONI_VERSION_MINOR) /** OpenNI version (in string format): "Major.Minor.Maintenance.Build-Platform (MMM DD YYYY HH:MM:SS)". */ #define ONI_VERSION_STRING \ ONI_BRIEF_VERSION_STRING "-" \ ONI_PLATFORM_STRING " (" ONI_TIMESTAMP ")" libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/OpenNI.h000066400000000000000000002676261264163024100300600ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _OPENNI_H_ #define _OPENNI_H_ #include "OniPlatform.h" #include "OniProperties.h" #include "OniEnums.h" #include "OniCAPI.h" #include "OniCProperties.h" /** openni is the namespace of the entire C++ API of OpenNI */ namespace openni { /** Pixel type used to store depth images. */ typedef uint16_t DepthPixel; /** Pixel type used to store IR images. */ typedef uint16_t Grayscale16Pixel; // structs /** Holds an OpenNI version number, which consists of four separate numbers in the format: @c major.minor.maintenance.build. For example: 2.0.0.20. */ typedef struct { /** Major version number, incremented for major API restructuring. */ int major; /** Minor version number, incremented when significant new features added. */ int minor; /** Maintenance build number, incremented for new releases that primarily provide minor bug fixes. */ int maintenance; /** Build number. Incremented for each new API build. Generally not shown on the installer and download site. */ int build; } Version; /** Holds the value of a single color image pixel in 24-bit RGB format. */ typedef struct { /* Red value of this pixel. */ uint8_t r; /* Green value of this pixel. */ uint8_t g; /* Blue value of this pixel. */ uint8_t b; } RGB888Pixel; /** Holds the value of two pixels in YUV422 format (Luminance/Chrominance,16-bits/pixel). The first pixel has the values y1, u, v. The second pixel has the values y2, u, v. */ typedef struct { /** First chrominance value for two pixels, stored as blue luminance difference signal. */ uint8_t u; /** Overall luminance value of first pixel. */ uint8_t y1; /** Second chrominance value for two pixels, stored as red luminance difference signal. */ uint8_t v; /** Overall luminance value of second pixel. */ uint8_t y2; } YUV422DoublePixel; /** This special URI can be passed to @ref Device::open() when the application has no concern for a specific device. */ #if ONI_PLATFORM != ONI_PLATFORM_WIN32 #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic push #endif static const char* ANY_DEVICE = NULL; #if ONI_PLATFORM != ONI_PLATFORM_WIN32 #pragma GCC diagnostic pop #endif /** Provides a simple array class used throughout the API. Wraps a primitive array of objects, holding the elements and their count. */ template class Array { public: /** Default constructor. Creates an empty Array and sets the element count to zero. */ Array() : m_data(NULL), m_count(0), m_owner(false) {} /** Constructor. Creates new Array from an existing primitive array of known size. @tparam [in] T Object type this Array will contain. @param [in] data Pointer to a primitive array of objects of type T. @param [in] count Number of elements in the primitive array pointed to by data. */ Array(const T* data, int count) : m_owner(false) { _setData(data, count); } /** Destructor. Destroys the Array object. */ ~Array() { clear(); } /** Getter function for the Array size. @returns Current number of elements in the Array. */ int getSize() const { return m_count; } /** Implements the array indexing operator for the Array class. */ const T& operator[](int index) const {return m_data[index];} /** @internal Setter function for data. Causes this array to wrap an existing primitive array of specified type. The optional data ownership flag controls whether the primitive array this Array wraps will be destroyed when this Array is deconstructed. @param [in] T Type of objects array will contain. @param [in] data Pointer to first object in list. @param [in] count Number of objects in list. @param [in] isOwner Optional flag to indicate data ownership */ void _setData(const T* data, int count, bool isOwner = false) { clear(); m_count = count; m_owner = isOwner; if (!isOwner) { m_data = data; } else { m_data = new T[count]; memcpy((void*)m_data, data, count*sizeof(T)); } } private: Array(const Array&); Array& operator=(const Array&); void clear() { if (m_owner && m_data != NULL) delete []m_data; m_owner = false; m_data = NULL; m_count = 0; } const T* m_data; int m_count; bool m_owner; }; // Forward declaration of all class SensorInfo; class VideoStream; class VideoFrameRef; class Device; class OpenNI; class CameraSettings; class PlaybackControl; /** Encapsulates a group of settings for a @ref VideoStream. Settings stored include frame rate, resolution, and pixel format. This class is used as an input for changing the settings of a @ref VideoStream, as well as an output for reporting the current settings of that class. It is also used by @ref SensorInfo to report available video modes of a stream. Recommended practice is to use @ref SensorInfo::getSupportedVideoModes() to obtain a list of valid video modes, and then to use items from that list to pass new settings to @ref VideoStream. This is much less likely to produce an invalid video mode than instantiating and manually changing objects of this class. */ class VideoMode : private OniVideoMode { public: /** Default constructor, creates an empty VideoMode object. Application programs should, in most cases, use the copy constructor to copy an existing valid video mode. This is much less error prone that creating and attempting to configure a new VideoMode from scratch. */ VideoMode() {} /** Copy constructor, creates a new VideoMode identical to an existing VideoMode. @param [in] other Existing VideoMode to copy. */ VideoMode(const VideoMode& other) { *this = other; } /** Assignment operator. Sets the pixel format, frame rate, and resolution of this VideoMode to equal that of a different VideoMode. @param [in] other Existing VideoMode to copy settings from. */ VideoMode& operator=(const VideoMode& other) { setPixelFormat(other.getPixelFormat()); setResolution(other.getResolutionX(), other.getResolutionY()); setFps(other.getFps()); return *this; } /** Getter function for the pixel format of this VideoMode. @returns Current pixel format setting of this VideoMode. */ PixelFormat getPixelFormat() const { return (PixelFormat)pixelFormat; } /** Getter function for the X resolution of this VideoMode. @returns Current horizontal resolution of this VideoMode, in pixels. */ int getResolutionX() const { return resolutionX; } /** Getter function for the Y resolution of this VideoMode. @returns Current vertical resolution of this VideoMode, in pixels. */ int getResolutionY() const {return resolutionY;} /** Getter function for the frame rate of this VideoMode. @returns Current frame rate, measured in frames per second. */ int getFps() const { return fps; } /** Setter function for the pixel format of this VideoMode. Application use of this function is not recommended. Instead, use @ref SensorInfo::getSupportedVideoModes() to obtain a list of valid video modes. @param [in] format Desired new pixel format for this VideoMode. */ void setPixelFormat(PixelFormat format) { this->pixelFormat = (OniPixelFormat)format; } /** Setter function for the resolution of this VideoMode. Application use of this function is not recommended. Instead, use @ref SensorInfo::getSupportedVideoModes() to obtain a list of valid video modes. @param [in] resolutionX Desired new horizontal resolution in pixels. @param [in] resolutionY Desired new vertical resolution in pixels. */ void setResolution(int resolutionX, int resolutionY) { this->resolutionX = resolutionX; this->resolutionY = resolutionY; } /** Setter function for the frame rate. Application use of this function is not recommended. Instead, use @ref SensorInfo::getSupportedVideoModes() to obtain a list of valid video modes. @param [in] fps Desired new frame rate, measured in frames per second. */ void setFps(int fps) { this->fps = fps; } friend class SensorInfo; friend class VideoStream; friend class VideoFrameRef; }; /** The SensorInfo class encapsulates all info related to a specific sensor in a specific device. A @ref Device object holds a SensorInfo object for each sensor it contains. A @ref VideoStream object holds one SensorInfo object, describing the sensor used to produce that stream. A given SensorInfo object will contain the type of the sensor (Depth, IR or Color), and a list of all video modes that the sensor can support. Each available video mode will have a single VideoMode object that can be queried to get the details of that mode. SensorInfo objects should be the only source of VideoMode objects for the vast majority of application programs. Application programs will never directly instantiate objects of type SensorInfo. In fact, no public constructors are provided. SensorInfo objects should be obtained either from a Device or @ref VideoStream, and in turn be used to provide available video modes for that sensor. */ class SensorInfo { public: /** Provides the sensor type of the sensor this object is associated with. @returns Type of the sensor. */ SensorType getSensorType() const { return (SensorType)m_pInfo->sensorType; } /** Provides a list of video modes that this sensor can support. This function is the recommended method to be used by applications to obtain @ref VideoMode objects. @returns Reference to an array of @ref VideoMode objects, one for each supported video mode. */ const Array& getSupportedVideoModes() const { return m_videoModes; } private: SensorInfo(const SensorInfo&); SensorInfo& operator=(const SensorInfo&); SensorInfo() : m_pInfo(NULL), m_videoModes(NULL, 0) {} SensorInfo(const OniSensorInfo* pInfo) : m_pInfo(NULL), m_videoModes(NULL, 0) { _setInternal(pInfo); } void _setInternal(const OniSensorInfo* pInfo) { m_pInfo = pInfo; if (pInfo == NULL) { m_videoModes._setData(NULL, 0); } else { m_videoModes._setData(static_cast(pInfo->pSupportedVideoModes), pInfo->numSupportedVideoModes); } } const OniSensorInfo* m_pInfo; Array m_videoModes; friend class VideoStream; friend class Device; }; /** The DeviceInfo class encapsulates info related to a specific device. Applications will generally obtain objects of this type via calls to @ref OpenNI::enumerateDevices() or @ref openni::Device::getDeviceInfo(), and then use the various accessor functions to obtain specific information on that device. There should be no reason for application code to instantiate this object directly. */ class DeviceInfo : private OniDeviceInfo { public: /** Returns the device URI. URI can be used by @ref Device::open to open a specific device. The URI string format is determined by the driver. */ const char* getUri() const { return uri; } /** Returns a the vendor name for this device. */ const char* getVendor() const { return vendor; } /** Returns the device name for this device. */ const char* getName() const { return name; } /** Returns the USB VID code for this device. */ uint16_t getUsbVendorId() const { return usbVendorId; } /** Returns the USB PID code for this device. */ uint16_t getUsbProductId() const { return usbProductId; } friend class Device; friend class OpenNI; }; /** The @ref VideoFrameRef class encapsulates a single video frame - the output of a @ref VideoStream at a specific time. The data contained will be a single frame of color, IR, or depth video, along with associated meta data. An object of type @ref VideoFrameRef does not actually hold the data of the frame, but only a reference to it. The reference can be released by destroying the @ref VideoFrameRef object, or by calling the @ref release() method. The actual data of the frame is freed when the last reference to it is released. The usual way to obtain @ref VideoFrameRef objects is by a call to @ref VideoStream.:readFrame(). All data references by a @ref VideoFrameRef is stored as a primitive array of pixels. Each pixel will be of a type according to the configured pixel format (see @ref VideoMode). */ class VideoFrameRef { public: /** Default constructor. Creates a new empty @ref VideoFrameRef object. This object will be invalid until initialized by a call to @ref VideoStream::readFrame(). */ VideoFrameRef() { m_pFrame = NULL; } /** Destroy this object and release the reference to the frame. */ ~VideoFrameRef() { release(); } /** Copy constructor. Creates a new @ref VideoFrameRef object. The newly created object will reference the same frame current object references. @param [in] other Another @ref VideoFrameRef object. */ VideoFrameRef(const VideoFrameRef& other) : m_pFrame(NULL) { _setFrame(other.m_pFrame); } /** Make this @ref VideoFrameRef object reference the same frame that the @c other frame references. If this object referenced another frame before calling this method, the previous frame will be released. @param [in] other Another @ref VideoFrameRef object. */ VideoFrameRef& operator=(const VideoFrameRef& other) { _setFrame(other.m_pFrame); return *this; } /** Getter function for the size of the data contained by this object. Useful primarily when allocating buffers. @returns Current size of data pointed to by this object, measured in bytes. */ inline int getDataSize() const { return m_pFrame->dataSize; } /** Getter function for the array of data pointed to by this object. @returns Pointer to the actual frame data array. Type of data pointed to can be determined according to the pixel format (can be obtained by calling @ref getVideoMode()). */ inline const void* getData() const { return m_pFrame->data; } /** Getter function for the sensor type used to produce this frame. Used to determine whether this is an IR, Color or Depth frame. See the @ref SensorType enumeration for all possible return values from this function. @returns The type of sensor used to produce this frame. */ inline SensorType getSensorType() const { return (SensorType)m_pFrame->sensorType; } /** Returns a reference to the @ref VideoMode object assigned to this frame. This object describes the video mode the sensor was configured to when the frame was produced and can be used to determine the pixel format and resolution of the data. It will also provide the frame rate that the sensor was running at when it recorded this frame. @returns Reference to the @ref VideoMode assigned to this frame. */ inline const VideoMode& getVideoMode() const { return static_cast(m_pFrame->videoMode); } /** Provides a timestamp for the frame. The 'zero' point for this stamp is implementation specific, but all streams from the same device are guaranteed to use the same zero. This value can therefore be used to compute time deltas between frames from the same device, regardless of whether they are from the same stream. @returns Timestamp of frame, measured in microseconds from an arbitrary zero */ inline uint64_t getTimestamp() const { return m_pFrame->timestamp; } /** Frames are provided sequential frame ID numbers by the sensor that produced them. If frame synchronization has been enabled for a device via @ref Device::setDepthColorSyncEnabled(), then frame numbers for corresponding frames of depth and color are guaranteed to match. If frame synchronization is not enabled, then there is no guarantee of matching frame indexes between @ref VideoStream "VideoStreams". In the latter case, applications should use timestamps instead of frame indexes to align frames in time. @returns Index number for this frame. */ inline int getFrameIndex() const { return m_pFrame->frameIndex; } /** Gives the current width of this frame, measured in pixels. If cropping is enabled, this will be the width of the cropping window. If cropping is not enabled, then this will simply be equal to the X resolution of the @ref VideoMode used to produce this frame. @returns Width of this frame in pixels. */ inline int getWidth() const { return m_pFrame->width; } /** Gives the current height of this frame, measured in pixels. If cropping is enabled, this will be the length of the cropping window. If cropping is not enabled, then this will simply be equal to the Y resolution of the @ref VideoMode used to produce this frame. */ inline int getHeight() const { return m_pFrame->height; } /** Indicates whether cropping was enabled when the frame was produced. @return true if cropping is enabled, false otherwise */ inline bool getCroppingEnabled() const { return m_pFrame->croppingEnabled == TRUE; } /** Indicates the X coordinate of the upper left corner of the crop window. @return Distance of crop origin from left side of image, in pixels. */ inline int getCropOriginX() const { return m_pFrame->cropOriginX; } /** Indicates the Y coordinate of the upper left corner of the crop window. @return Distance of crop origin from top of image, in pixels. */ inline int getCropOriginY() const { return m_pFrame->cropOriginY; } /** Gives the length of one row of pixels, measured in bytes. Primarily useful for indexing the array which contains the data. @returns Stride of the array which contains the image for this frame, in bytes */ inline int getStrideInBytes() const { return m_pFrame->stride; } /** Check if this object references an actual frame. */ inline bool isValid() const { return m_pFrame != NULL; } /** Release the reference to the frame. Once this method is called, the object becomes invalid, and no method should be called other than the assignment operator, or passing this object to a @ref VideoStream::readFrame() call. */ void release() { if (m_pFrame != NULL) { oniFrameRelease(m_pFrame); m_pFrame = NULL; } } /** @internal */ void _setFrame(OniFrame* pFrame) { setReference(pFrame); if (pFrame != NULL) { oniFrameAddRef(pFrame); } } /** @internal */ OniFrame* _getFrame() { return m_pFrame; } private: friend class VideoStream; inline void setReference(OniFrame* pFrame) { // Initial - don't addref. This is the reference from OpenNI release(); m_pFrame = pFrame; } OniFrame* m_pFrame; // const!!? }; /** The @ref VideoStream object encapsulates a single video stream from a device. Once created, it is used to start data flow from the device, and to read individual frames of data. This is the central class used to obtain data in OpenNI. It provides the ability to manually read data in a polling loop, as well as providing events and a Listener class that can be used to implement event-driven data acquisition. Aside from the video data frames themselves, the class offers a number of functions used for obtaining information about a @ref VideoStream. Field of view, available video modes, and minimum and maximum valid pixel values can all be obtained. In addition to obtaining data, the @ref VideoStream object is used to set all configuration properties that apply to a specific stream (rather than to an entire device). In particular, it is used to control cropping, mirroring, and video modes. A pointer to a valid, initialized device that provides the desired stream type is required to create a stream. Several video streams can be created to stream data from the same sensor. This is useful if several components of an application need to read frames separately. While some device might allow different streams from the same sensor to have different configurations, most devices will have a single configuration for the sensor, shared by all streams. */ class VideoStream { public: /** The @ref VideoStream::NewFrameListener class is provided to allow the implementation of event driven frame reading. To use it, create a class that inherits from it and implement override the onNewFrame() method. Then, register your created class with an active @ref VideoStream using the @ref VideoStream::addNewFrameListener() function. Once this is done, the event handler function you implemented will be called whenever a new frame becomes available. You may call @ref VideoStream::readFrame() from within the event handler. */ class NewFrameListener { public: /** Default constructor. */ NewFrameListener() : m_callbackHandle(NULL) { } virtual ~NewFrameListener() { } /** Derived classes should implement this function to handle new frames. */ virtual void onNewFrame(VideoStream&) = 0; private: friend class VideoStream; static void ONI_CALLBACK_TYPE callback(OniStreamHandle streamHandle, void* pCookie) { NewFrameListener* pListener = (NewFrameListener*)pCookie; VideoStream stream; stream._setHandle(streamHandle); pListener->onNewFrame(stream); stream._setHandle(NULL); } OniCallbackHandle m_callbackHandle; }; class FrameAllocator { public: virtual ~FrameAllocator() {} virtual void* allocateFrameBuffer(int size) = 0; virtual void freeFrameBuffer(void* data) = 0; private: friend class VideoStream; static void* ONI_CALLBACK_TYPE allocateFrameBufferCallback(int size, void* pCookie) { FrameAllocator* pThis = (FrameAllocator*)pCookie; return pThis->allocateFrameBuffer(size); } static void ONI_CALLBACK_TYPE freeFrameBufferCallback(void* data, void* pCookie) { FrameAllocator* pThis = (FrameAllocator*)pCookie; pThis->freeFrameBuffer(data); } }; /** Default constructor. Creates a new, non-valid @ref VideoStream object. The object created will be invalid until its create() function is called with a valid Device. */ VideoStream() : m_stream(NULL), m_sensorInfo(), m_pCameraSettings(NULL), m_isOwner(true) {} /** Handle constructor. Creates a VideoStream object based on the given initialized handle. This object will not destroy the underlying handle when @ref destroy() or destructor is called */ explicit VideoStream(OniStreamHandle handle) : m_stream(NULL), m_sensorInfo(), m_pCameraSettings(NULL), m_isOwner(false) { _setHandle(handle); } /** Destructor. The destructor calls the destroy() function, but it is considered a best practice for applications to call destroy() manually on any @ref VideoStream that they run create() on. */ ~VideoStream() { destroy(); } /** Checks to see if this object has been properly initialized and currently points to a valid stream. @returns true if this object has been previously initialized, false otherwise. */ bool isValid() const { return m_stream != NULL; } /** Creates a stream of frames from a specific sensor type of a specific device. You must supply a reference to a Device that supplies the sensor type requested. You can use @ref Device::hasSensor() to check whether a given sensor is available on your target device before calling create(). @param [in] device A reference to the @ref Device you want to create the stream on. @param [in] sensorType The type of sensor the stream should produce data from. @returns Status code indicating success or failure for this operation. */ inline Status create(const Device& device, SensorType sensorType); /** Destroy this stream. This function is currently called automatically by the destructor, but it is considered a best practice for applications to manually call this function on any @ref VideoStream that they call create() for. */ inline void destroy(); /** Provides the @ref SensorInfo object associated with the sensor that is producing this @ref VideoStream. Note that this function will return NULL if the stream has not yet been initialized with the create() function. @ref SensorInfo is useful primarily as a means of learning which video modes are valid for this VideoStream. @returns Reference to the SensorInfo object associated with the sensor providing this stream. */ const SensorInfo& getSensorInfo() const { return m_sensorInfo; } /** Starts data generation from this video stream. */ Status start() { if (!isValid()) { return STATUS_ERROR; } return (Status)oniStreamStart(m_stream); } /** Stops data generation from this video stream. */ void stop() { if (!isValid()) { return; } oniStreamStop(m_stream); } /** Read the next frame from this video stream, delivered as a @ref VideoFrameRef. This is the primary method for manually obtaining frames of video data. If no new frame is available, the call will block until one is available. To avoid blocking, use @ref VideoStream::Listener to implement an event driven architecture. Another alternative is to use @ref OpenNI::waitForAnyStream() to wait for new frames from several streams. @param [out] pFrame Pointer to a @ref VideoFrameRef object to hold the reference to the new frame. @returns Status code to indicated success or failure of this function. */ Status readFrame(VideoFrameRef* pFrame) { if (!isValid()) { return STATUS_ERROR; } OniFrame* pOniFrame; Status rc = (Status)oniStreamReadFrame(m_stream, &pOniFrame); pFrame->setReference(pOniFrame); return rc; } /** Adds a new Listener to receive this VideoStream onNewFrame event. See @ref VideoStream::NewFrameListener for more information on implementing an event driven frame reading architecture. An instance of a listener can be added to only one source. @param [in] pListener Pointer to a @ref VideoStream::NewFrameListener object (or a derivative) that will respond to this event. @returns Status code indicating success or failure of the operation. */ Status addNewFrameListener(NewFrameListener* pListener) { if (!isValid()) { return STATUS_ERROR; } return (Status)oniStreamRegisterNewFrameCallback(m_stream, pListener->callback, pListener, &pListener->m_callbackHandle); } /** Removes a Listener from this video stream list. The listener removed will no longer receive new frame events from this stream. @param [in] pListener Pointer to the listener object to be removed. */ void removeNewFrameListener(NewFrameListener* pListener) { if (!isValid()) { return; } oniStreamUnregisterNewFrameCallback(m_stream, pListener->m_callbackHandle); pListener->m_callbackHandle = NULL; } /** Sets the frame buffers allocator for this video stream. @param [in] pAllocator Pointer to the frame buffers allocator object. Pass NULL to return to default frame allocator. @returns ONI_STATUS_OUT_OF_FLOW The frame buffers allocator cannot be set while stream is streaming. */ Status setFrameBuffersAllocator(FrameAllocator* pAllocator) { if (!isValid()) { return STATUS_ERROR; } if (pAllocator == NULL) { return (Status)oniStreamSetFrameBuffersAllocator(m_stream, NULL, NULL, NULL); } else { return (Status)oniStreamSetFrameBuffersAllocator(m_stream, pAllocator->allocateFrameBufferCallback, pAllocator->freeFrameBufferCallback, pAllocator); } } /** @internal Get an internal handle. This handle can be used via the C API. */ OniStreamHandle _getHandle() const { return m_stream; } /** Gets an object through which several camera settings can be configured. @returns NULL if the stream doesn't support camera settings. */ CameraSettings* getCameraSettings() {return m_pCameraSettings;} /** General function for obtaining the value of stream specific properties. There are convenience functions available for all commonly used properties, so it is not expected that applications will make direct use of the getProperty function very often. @param [in] propertyId The numerical ID of the property to be queried. @param [out] data Place to store the value of the property. @param [in,out] dataSize IN: Size of the buffer passed in the @c data argument. OUT: the actual written size. @returns Status code indicating success or failure of this operation. */ Status getProperty(int propertyId, void* data, int* dataSize) const { if (!isValid()) { return STATUS_ERROR; } return (Status)oniStreamGetProperty(m_stream, propertyId, data, dataSize); } /** General function for setting the value of stream specific properties. There are convenience functions available for all commonly used properties, so it is not expected that applications will make direct use of the setProperty function very often. @param [in] propertyId The numerical ID of the property to be set. @param [in] data Place to store the data to be written to the property. @param [in] dataSize Size of the data to be written to the property. @returns Status code indicating success or failure of this operation. */ Status setProperty(int propertyId, const void* data, int dataSize) { if (!isValid()) { return STATUS_ERROR; } return (Status)oniStreamSetProperty(m_stream, propertyId, data, dataSize); } /** Get the current video mode information for this video stream. This includes its resolution, fps and stream format. @returns Current video mode information for this video stream. */ VideoMode getVideoMode() const { VideoMode videoMode; getProperty(STREAM_PROPERTY_VIDEO_MODE, static_cast(&videoMode)); return videoMode; } /** Changes the current video mode of this stream. Recommended practice is to use @ref Device::getSensorInfo(), and then @ref SensorInfo::getSupportedVideoModes() to obtain a list of valid video mode settings for this stream. Then, pass a valid @ref VideoMode to @ref setVideoMode to ensure correct operation. @param [in] videoMode Desired new video mode for this stream. returns Status code indicating success or failure of this operation. */ Status setVideoMode(const VideoMode& videoMode) { return setProperty(STREAM_PROPERTY_VIDEO_MODE, static_cast(videoMode)); } /** Provides the maximum possible value for pixels obtained by this stream. This is most useful for getting the maximum possible value of depth streams. @returns Maximum possible pixel value. */ int getMaxPixelValue() const { int maxValue; Status rc = getProperty(STREAM_PROPERTY_MAX_VALUE, &maxValue); if (rc != STATUS_OK) { return 0; } return maxValue; } /** Provides the smallest possible value for pixels obtains by this VideoStream. This is most useful for getting the minimum possible value that will be reported by a depth stream. @returns Minimum possible pixel value that can come from this stream. */ int getMinPixelValue() const { int minValue; Status rc = getProperty(STREAM_PROPERTY_MIN_VALUE, &minValue); if (rc != STATUS_OK) { return 0; } return minValue; } /** Checks whether this stream supports cropping. @returns true if the stream supports cropping, false if it does not. */ bool isCroppingSupported() const { return isPropertySupported(STREAM_PROPERTY_CROPPING); } /** Obtains the current cropping settings for this stream. @param [out] pOriginX X coordinate of the upper left corner of the cropping window @param [out] pOriginY Y coordinate of the upper left corner of the cropping window @param [out] pWidth Horizontal width of the cropping window, in pixels @param [out] pHeight Vertical width of the cropping window, in pixels returns true if cropping is currently enabled, false if it is not. */ bool getCropping(int* pOriginX, int* pOriginY, int* pWidth, int* pHeight) const { OniCropping cropping; bool enabled = false; Status rc = getProperty(STREAM_PROPERTY_CROPPING, &cropping); if (rc == STATUS_OK) { *pOriginX = cropping.originX; *pOriginY = cropping.originY; *pWidth = cropping.width; *pHeight = cropping.height; enabled = (cropping.enabled == TRUE); } return enabled; } /** Changes the cropping settings for this stream. You can use the @ref isCroppingSupported() function to make sure cropping is supported before calling this function. @param [in] originX New X coordinate of the upper left corner of the cropping window. @param [in] originY New Y coordinate of the upper left corner of the cropping window. @param [in] width New horizontal width for the cropping window, in pixels. @param [in] height New vertical height for the cropping window, in pixels. @returns Status code indicating success or failure of this operation. */ Status setCropping(int originX, int originY, int width, int height) { OniCropping cropping; cropping.enabled = true; cropping.originX = originX; cropping.originY = originY; cropping.width = width; cropping.height = height; return setProperty(STREAM_PROPERTY_CROPPING, cropping); } /** Disables cropping. @returns Status code indicating success or failure of this operation. */ Status resetCropping() { OniCropping cropping; cropping.enabled = false; return setProperty(STREAM_PROPERTY_CROPPING, cropping); } /** Check whether mirroring is currently turned on for this stream. @returns true if mirroring is currently enabled, false otherwise. */ bool getMirroringEnabled() const { OniBool enabled; Status rc = getProperty(STREAM_PROPERTY_MIRRORING, &enabled); if (rc != STATUS_OK) { return false; } return enabled == TRUE; } /** Enable or disable mirroring for this stream. @param [in] isEnabled true to enable mirroring, false to disable it. @returns Status code indicating the success or failure of this operation. */ Status setMirroringEnabled(bool isEnabled) { return setProperty(STREAM_PROPERTY_MIRRORING, isEnabled ? TRUE : FALSE); } /** Gets the horizontal field of view of frames received from this stream. @returns Horizontal field of view, in radians. */ float getHorizontalFieldOfView() const { float horizontal = 0; getProperty(STREAM_PROPERTY_HORIZONTAL_FOV, &horizontal); return horizontal; } /** Gets the vertical field of view of frames received from this stream. @returns Vertical field of view, in radians. */ float getVerticalFieldOfView() const { float vertical = 0; getProperty(STREAM_PROPERTY_VERTICAL_FOV, &vertical); return vertical; } /** Function for setting a value of a stream property using an arbitrary input type. There are convenience functions available for all commonly used properties, so it is not expected that applications will make direct use of this function very often. @tparam [in] T Data type of the value to be passed to the property. @param [in] propertyId The numerical ID of the property to be set. @param [in] value Data to be sent to the property. @returns Status code indicating success or failure of this operation. */ template Status setProperty(int propertyId, const T& value) { return setProperty(propertyId, &value, sizeof(T)); } /** Function for getting the value from a property using an arbitrary output type. There are convenience functions available for all commonly used properties, so it is not expected that applications will make direct use of this function very often. @tparam [in] T Data type of the value to be read. @param [in] propertyId The numerical ID of the property to be read. @param [in, out] value Pointer to a place to store the value read from the property. @returns Status code indicating success or failure of this operation. */ template Status getProperty(int propertyId, T* value) const { int size = sizeof(T); return getProperty(propertyId, value, &size); } /** Checks if a specific property is supported by the video stream. @param [in] propertyId Property to be checked. @returns true if the property is supported, false otherwise. */ bool isPropertySupported(int propertyId) const { if (!isValid()) { return false; } return oniStreamIsPropertySupported(m_stream, propertyId) == TRUE; } /** Invokes a command that takes an arbitrary data type as its input. It is not expected that application code will need this function frequently, as all commonly used properties have higher level functions provided. @param [in] commandId Numerical code of the property to be invoked. @param [in] data Data to be passed to the property. @param [in] dataSize size of the buffer passed in @c data. @returns Status code indicating success or failure of this operation. */ Status invoke(int commandId, void* data, int dataSize) { if (!isValid()) { return STATUS_ERROR; } return (Status)oniStreamInvoke(m_stream, commandId, data, dataSize); } /** Invokes a command that takes an arbitrary data type as its input. It is not expected that application code will need this function frequently, as all commonly used properties have higher level functions provided. @tparam [in] T Type of data to be passed to the property. @param [in] commandId Numerical code of the property to be invoked. @param [in] value Data to be passed to the property. @returns Status code indicating success or failure of this operation. */ template Status invoke(int commandId, T& value) { return invoke(commandId, &value, sizeof(T)); } /** Checks if a specific command is supported by the video stream. @param [in] commandId Command to be checked. @returns true if the command is supported, false otherwise. */ bool isCommandSupported(int commandId) const { if (!isValid()) { return false; } return (Status)oniStreamIsCommandSupported(m_stream, commandId) == TRUE; } private: friend class Device; void _setHandle(OniStreamHandle stream) { m_sensorInfo._setInternal(NULL); m_stream = stream; if (stream != NULL) { m_sensorInfo._setInternal(oniStreamGetSensorInfo(m_stream)); } } private: VideoStream(const VideoStream& other); VideoStream& operator=(const VideoStream& other); OniStreamHandle m_stream; SensorInfo m_sensorInfo; CameraSettings* m_pCameraSettings; bool m_isOwner; }; /** The Device object abstracts a specific device; either a single hardware device, or a file device holding a recording from a hardware device. It offers the ability to connect to the device, and obtain information about its configuration and the data streams it can offer. It provides the means to query and change all configuration parameters that apply to the device as a whole. This includes enabling depth/color image registration and frame synchronization. Devices are used when creating and initializing @ref VideoStream "VideoStreams" -- you will need a valid pointer to a Device in order to use the VideoStream.create() function. This, along with configuration, is the primary use of this class for application developers. Before devices can be created, @ref OpenNI::initialize() must have been run to make the device drivers on the system available to the API. */ class Device { public: /** Default constructor. Creates a new empty Device object. This object will be invalid until it is initialized by calling its open() function. */ Device() : m_pPlaybackControl(NULL), m_device(NULL), m_isOwner(true) { clearSensors(); } /** Handle constructor. Creates a Device object based on the given initialized handle. This object will not destroy the underlying handle when @ref close() or destructor is called */ explicit Device(OniDeviceHandle handle) : m_pPlaybackControl(NULL), m_device(NULL), m_isOwner(false) { _setHandle(handle); } /** The destructor calls the @ref close() function, but it is considered a best practice for applications to call @ref close() manually on any @ref Device that they run @ref open() on. */ ~Device() { if (m_device != NULL) { close(); } } /** Opens a device. This can either open a device chosen arbitrarily from all devices on the system, or open a specific device selected by passing this function the device URI. To open any device, simply pass the constant@ref ANY_DEVICE to this function. If multiple devices are connected to the system, then one of them will be opened. This procedure is most useful when it is known that exactly one device is (or can be) connected to the system. In that case, requesting a list of all devices and iterating through it would be a waste of effort. If multiple devices are (or may be) connected to a system, then a URI will be required to select a specific device to open. There are two ways to obtain a URI: from a DeviceConnected event, or by calling @ref OpenNI::enumerateDevices(). In the case of a DeviceConnected event, the @ref OpenNI::Listener will be provided with a DeviceInfo object as an argument to its @ref OpenNI::Listener::onDeviceConnected "onDeviceConnected()" function. The DeviceInfo.getUri() function can then be used to obtain the URI. If the application is not using event handlers, then it can also call the static function @ref OpenNI::enumerateDevices(). This will return an array of @ref DeviceInfo objects, one for each device currently available to the system. The application can then iterate through this list and select the desired device. The URI is again obtained via the @ref DeviceInfo::getUri() function. Standard codes of type Status are returned indicating whether opening was successful. @param [in] uri String containing the URI of the device to be opened, or @ref ANY_DEVICE. @returns Status code with the outcome of the open operation. @remark For opening a recording file, pass the file path as a uri. */ inline Status open(const char* uri); /** Closes the device. This properly closes any files or shuts down hardware, as appropriate. This function is currently called by the destructor if not called manually by application code, but it is considered a best practice to manually close any device that was opened. */ inline void close(); /** Provides information about this device in the form of a DeviceInfo object. This object can be used to access the URI of the device, as well as various USB descriptor strings that might be useful to an application. Note that valid device info will not be available if this device has not yet been opened. If you are trying to obtain a URI to open a device, use OpenNI::enumerateDevices() instead. @returns DeviceInfo object for this Device */ const DeviceInfo& getDeviceInfo() const { return m_deviceInfo; } /** This function checks to see if one of the specific sensor types defined in @ref SensorType is available on this device. This allows an application to, for example, query for the presence of a depth sensor, or color sensor. @param [in] sensorType of sensor to query for @returns true if the Device supports the sensor queried, false otherwise. */ bool hasSensor(SensorType sensorType) { int i; for (i = 0; (i < ONI_MAX_SENSORS) && (m_aSensorInfo[i].m_pInfo != NULL); ++i) { if (m_aSensorInfo[i].getSensorType() == sensorType) { return true; } } if (i == ONI_MAX_SENSORS) { return false; } const OniSensorInfo* pInfo = oniDeviceGetSensorInfo(m_device, (OniSensorType)sensorType); if (pInfo == NULL) { return false; } m_aSensorInfo[i]._setInternal(pInfo); return true; } /** Get the @ref SensorInfo for a specific sensor type on this device. The @ref SensorInfo is useful primarily for determining which video modes are supported by the sensor. @param [in] sensorType of sensor to get information about. @returns SensorInfo object corresponding to the sensor type specified, or NULL if such a sensor is not available from this device. */ const SensorInfo* getSensorInfo(SensorType sensorType) { int i; for (i = 0; (i < ONI_MAX_SENSORS) && (m_aSensorInfo[i].m_pInfo != NULL); ++i) { if (m_aSensorInfo[i].getSensorType() == sensorType) { return &m_aSensorInfo[i]; } } // not found. check to see we have additional space if (i == ONI_MAX_SENSORS) { return NULL; } const OniSensorInfo* pInfo = oniDeviceGetSensorInfo(m_device, (OniSensorType)sensorType); if (pInfo == NULL) { return NULL; } m_aSensorInfo[i]._setInternal(pInfo); return &m_aSensorInfo[i]; } /** @internal Get an internal handle. This handle can be used via the C API. */ OniDeviceHandle _getHandle() const { return m_device; } /** Gets an object through which playback of a file device can be controlled. @returns NULL if this device is not a file device. */ PlaybackControl* getPlaybackControl() {return m_pPlaybackControl;} /** Get the value of a general property of the device. There are convenience functions for all the commonly used properties, such as image registration and frame synchronization. It is expected for this reason that this function will rarely be directly used by applications. @param [in] propertyId Numerical ID of the property you would like to check. @param [out] data Place to store the value of the property. @param [in,out] dataSize IN: Size of the buffer passed in the @c data argument. OUT: the actual written size. @returns Status code indicating results of this operation. */ Status getProperty(int propertyId, void* data, int* dataSize) const { return (Status)oniDeviceGetProperty(m_device, propertyId, data, dataSize); } /** Sets the value of a general property of the device. There are convenience functions for all the commonly used properties, such as image registration and frame synchronization. It is expected for this reason that this function will rarely be directly used by applications. @param [in] propertyId The numerical ID of the property to be set. @param [in] data Place to store the data to be written to the property. @param [in] dataSize Size of the data to be written to the property. @returns Status code indicating results of this operation. */ Status setProperty(int propertyId, const void* data, int dataSize) { return (Status)oniDeviceSetProperty(m_device, propertyId, data, dataSize); } /** Checks to see if this device can support registration of color video and depth video. Image registration is used to properly superimpose two images from cameras located at different points in space. Please see the OpenNi 2.0 Programmer's Guide for more information about registration. @returns true if image registration is supported by this device, false otherwise. */ bool isImageRegistrationModeSupported(ImageRegistrationMode mode) const { return (oniDeviceIsImageRegistrationModeSupported(m_device, (OniImageRegistrationMode)mode) == TRUE); } /** Gets the current image registration mode of this device. Image registration is used to properly superimpose two images from cameras located at different points in space. Please see the OpenNi 2.0 Programmer's Guide for more information about registration. @returns Current image registration mode. See @ref ImageRegistrationMode for possible return values. */ ImageRegistrationMode getImageRegistrationMode() const { ImageRegistrationMode mode; Status rc = getProperty(DEVICE_PROPERTY_IMAGE_REGISTRATION, &mode); if (rc != STATUS_OK) { return IMAGE_REGISTRATION_OFF; } return mode; } /** Sets the image registration on this device. Image registration is used to properly superimpose two images from cameras located at different points in space. Please see the OpenNi 2.0 Programmer's Guide for more information about registration. See @ref ImageRegistrationMode for a list of valid settings to pass to this function. It is a good practice to first check if the mode is supported by calling @ref isImageRegistrationModeSupported(). @param [in] mode Desired new value for the image registration mode. @returns Status code for the operation. */ Status setImageRegistrationMode(ImageRegistrationMode mode) { return setProperty(DEVICE_PROPERTY_IMAGE_REGISTRATION, mode); } /** Checks whether this Device object is currently connected to an actual file or hardware device. @returns true if the Device is connected, false otherwise. */ bool isValid() const { return m_device != NULL; } /** Checks whether this device is a file device (i.e. a recording). @returns true if this is a file device, false otherwise. */ bool isFile() const { return isPropertySupported(DEVICE_PROPERTY_PLAYBACK_SPEED) && isPropertySupported(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED) && isCommandSupported(DEVICE_COMMAND_SEEK); } /** Used to turn the depth/color frame synchronization feature on and off. When frame synchronization is enabled, the device will deliver depth and image frames that are separated in time by some maximum value. When disabled, the phase difference between depth and image frame generation cannot be guaranteed. @param [in] isEnabled Set to TRUE to enable synchronization, FALSE to disable it @returns Status code indicating success or failure of this operation */ Status setDepthColorSyncEnabled(bool isEnabled) { Status rc = STATUS_OK; if (isEnabled) { rc = (Status)oniDeviceEnableDepthColorSync(m_device); } else { oniDeviceDisableDepthColorSync(m_device); } return rc; } bool getDepthColorSyncEnabled() { return oniDeviceGetDepthColorSyncEnabled(m_device) == TRUE; } /** Sets a property that takes an arbitrary data type as its input. It is not expected that application code will need this function frequently, as all commonly used properties have higher level functions provided. @tparam T Type of data to be passed to the property. @param [in] propertyId The numerical ID of the property to be set. @param [in] value Place to store the data to be written to the property. @returns Status code indicating success or failure of this operation. */ template Status setProperty(int propertyId, const T& value) { return setProperty(propertyId, &value, sizeof(T)); } /** Checks a property that provides an arbitrary data type as its output. It is not expected that application code will need this function frequently, as all commonly used properties have higher level functions provided. @tparam [in] T Data type of the value to be read. @param [in] propertyId The numerical ID of the property to be read. @param [in, out] value Pointer to a place to store the value read from the property. @returns Status code indicating success or failure of this operation. */ template Status getProperty(int propertyId, T* value) const { int size = sizeof(T); return getProperty(propertyId, value, &size); } /** Checks if a specific property is supported by the device. @param [in] propertyId Property to be checked. @returns true if the property is supported, false otherwise. */ bool isPropertySupported(int propertyId) const { return oniDeviceIsPropertySupported(m_device, propertyId) == TRUE; } /** Invokes a command that takes an arbitrary data type as its input. It is not expected that application code will need this function frequently, as all commonly used properties have higher level functions provided. @param [in] commandId Numerical code of the property to be invoked. @param [in] data Data to be passed to the property. @param [in] dataSize size of the buffer passed in @c data. @returns Status code indicating success or failure of this operation. */ Status invoke(int commandId, void* data, int dataSize) { return (Status)oniDeviceInvoke(m_device, commandId, data, dataSize); } /** Invokes a command that takes an arbitrary data type as its input. It is not expected that application code will need this function frequently, as all commonly used properties have higher level functions provided. @tparam [in] T Type of data to be passed to the property. @param [in] propertyId Numerical code of the property to be invoked. @param [in] value Data to be passed to the property. @returns Status code indicating success or failure of this operation. */ template Status invoke(int propertyId, T& value) { return invoke(propertyId, &value, sizeof(T)); } /** Checks if a specific command is supported by the device. @param [in] commandId Command to be checked. @returns true if the command is supported, false otherwise. */ bool isCommandSupported(int commandId) const { return oniDeviceIsCommandSupported(m_device, commandId) == TRUE; } /** @internal **/ inline Status _openEx(const char* uri, const char* mode); private: Device(const Device&); Device& operator=(const Device&); void clearSensors() { for (int i = 0; i < ONI_MAX_SENSORS; ++i) { m_aSensorInfo[i]._setInternal(NULL); } } inline Status _setHandle(OniDeviceHandle deviceHandle); private: PlaybackControl* m_pPlaybackControl; OniDeviceHandle m_device; DeviceInfo m_deviceInfo; SensorInfo m_aSensorInfo[ONI_MAX_SENSORS]; bool m_isOwner; }; /** * The PlaybackControl class provides access to a series of specific to playing back * a recording from a file device. * * When playing a stream back from a recording instead of playing from a live device, * it is possible to vary playback speed, change the current time location (ie * fast forward / rewind / seek), specify whether the playback should be repeated at the end * of the recording, and query the total size of the recording. * * Since none of these functions make sense in the context of a physical device, they are * split out into a seperate playback control class. To use, simply create your file device, * create a PlaybackControl, and then attach the PlaybackControl to the file device. */ class PlaybackControl { public: /** * Deconstructor. Destroys a PlaybackControl class. The deconstructor presently detaches * from its recording automatically, but it is considered a best practice for applications to * manually detach from any stream that was attached to. */ ~PlaybackControl() { detach(); } /** * Getter function for the current playback speed of this device. * * This value is expressed as a multiple of the speed the original * recording was taken at. For example, if the original recording was at 30fps, and * playback speed is set to 0.5, then the recording will play at 15fps. If playback speed * is set to 2.0, then the recording would playback at 60fps. * * In addition, there are two "special" values. A playback speed of 0.0 indicates that the * playback should occur as fast as the system is capable of returning frames. This is * most useful when testing algorithms on large datasets, as it enables playback to be * done at a much higher rate than would otherwise be possible. * * A value of -1 indicates that speed is "manual". In this mode, new frames will only * become available when an application manually reads them. If used in a polling loop, * this setting also enables systems to read and process frames limited only by * available processing speeds. * * @returns Current playback speed of the device, measured as ratio of recording speed. */ float getSpeed() const { if (!isValid()) { return 0.0f; } float speed; Status rc = m_pDevice->getProperty(DEVICE_PROPERTY_PLAYBACK_SPEED, &speed); if (rc != STATUS_OK) { return 1.0f; } return speed; } /** * Setter function for the playback speed of the device. For a full explaination of * what this value means @see PlaybackControl::getSpeed(). * * @param [in] speed Desired new value of playback speed, as ratio of original recording. * @returns Status code indicating success or failure of this operation. */ Status setSpeed(float speed) { if (!isValid()) { return STATUS_NO_DEVICE; } return m_pDevice->setProperty(DEVICE_PROPERTY_PLAYBACK_SPEED, speed); } /** * Gets the current repeat setting of the file device. * * @returns true if repeat is enabled, false if not enabled. */ bool getRepeatEnabled() const { if (!isValid()) { return false; } OniBool repeat; Status rc = m_pDevice->getProperty(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED, &repeat); if (rc != STATUS_OK) { return false; } return repeat == TRUE; } /** * Changes the current repeat mode of the device. If repeat mode is turned on, then the recording will * begin playback again at the beginning after the last frame is read. If turned off, no more frames * will become available after last frame is read. * * @param [in] repeat New value for repeat -- true to enable, false to disable * @returns Status code indicating success or failure of this operations. */ Status setRepeatEnabled(bool repeat) { if (!isValid()) { return STATUS_NO_DEVICE; } return m_pDevice->setProperty(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED, repeat ? TRUE : FALSE); } /** * Seeks within a VideoStream to a given FrameID. Note that when this function is called on one * stream, all other streams will also be changed to the corresponding place in the recording. The FrameIDs * of different streams may not match, since FrameIDs may differ for streams that are not synchronized, but * the recording will set all streams to the same moment in time. * * @param [in] stream Stream for which the frameIndex value is valid. * @param [in] frameIndex Frame index to move playback to * @returns Status code indicating success or failure of this operation */ Status seek(const VideoStream& stream, int frameIndex) { if (!isValid()) { return STATUS_NO_DEVICE; } OniSeek seek; seek.frameIndex = frameIndex; seek.stream = stream._getHandle(); return m_pDevice->invoke(DEVICE_COMMAND_SEEK, seek); } /** * Provides the a count of frames that this recording contains for a given stream. This is useful * both to determine the length of the recording, and to ensure that a valid Frame Index is set when using * the @ref PlaybackControl::seek() function. * * @param [in] stream The video stream to count frames for * @returns Number of frames in provided @ref VideoStream, or 0 if the stream is not part of the recording */ int getNumberOfFrames(const VideoStream& stream) const { int numOfFrames = -1; Status rc = stream.getProperty(STREAM_PROPERTY_NUMBER_OF_FRAMES, &numOfFrames); if (rc != STATUS_OK) { return 0; } return numOfFrames; } bool isValid() const { return m_pDevice != NULL; } private: Status attach(Device* device) { if (!device->isValid() || !device->isFile()) { return STATUS_ERROR; } detach(); m_pDevice = device; return STATUS_OK; } void detach() { m_pDevice = NULL; } friend class Device; PlaybackControl(Device* pDevice) : m_pDevice(NULL) { if (pDevice != NULL) { attach(pDevice); } } Device* m_pDevice; }; class CameraSettings { public: // setters Status setAutoExposureEnabled(bool enabled) { return setProperty(STREAM_PROPERTY_AUTO_EXPOSURE, enabled ? TRUE : FALSE); } Status setAutoWhiteBalanceEnabled(bool enabled) { return setProperty(STREAM_PROPERTY_AUTO_WHITE_BALANCE, enabled ? TRUE : FALSE); } bool getAutoExposureEnabled() const { OniBool enabled = FALSE; Status rc = getProperty(STREAM_PROPERTY_AUTO_EXPOSURE, &enabled); return rc == STATUS_OK && enabled == TRUE; } bool getAutoWhiteBalanceEnabled() const { OniBool enabled = FALSE; Status rc = getProperty(STREAM_PROPERTY_AUTO_WHITE_BALANCE, &enabled); return rc == STATUS_OK && enabled == TRUE; } Status setGain(int gain) { return setProperty(STREAM_PROPERTY_GAIN, gain); } Status setExposure(int exposure) { return setProperty(STREAM_PROPERTY_EXPOSURE, exposure); } int getGain() { int gain; Status rc = getProperty(STREAM_PROPERTY_GAIN, &gain); if (rc != STATUS_OK) { return 100; } return gain; } int getExposure() { int exposure; Status rc = getProperty(STREAM_PROPERTY_EXPOSURE, &exposure); if (rc != STATUS_OK) { return 0; } return exposure; } bool isValid() const {return m_pStream != NULL;} private: template Status getProperty(int propertyId, T* value) const { if (!isValid()) return STATUS_NOT_SUPPORTED; return m_pStream->getProperty(propertyId, value); } template Status setProperty(int propertyId, const T& value) { if (!isValid()) return STATUS_NOT_SUPPORTED; return m_pStream->setProperty(propertyId, value); } friend class VideoStream; CameraSettings(VideoStream* pStream) { m_pStream = pStream; } VideoStream* m_pStream; }; /** * The OpenNI class is a static entry point to the library. It is used by every OpenNI 2.0 * application to initialize the SDK and drivers to enable creation of valid device objects. * * It also defines a listener class and events that enable for event driven notification of * device connection, device disconnection, and device configuration changes. * * In addition, it gives access to SDK version information and provides a function that allows * you to wait for data to become available on any one of a list of streams (as opposed to * waiting for data on one specific stream with functions provided by the VideoStream class) * */ class OpenNI { public: /** * The OpenNI::DeviceConnectedListener class provides a means of registering for, and responding to * when a device is connected. * * onDeviceConnected is called whenever a new device is connected to the system (ie this event * would be triggered when a new sensor is manually plugged into the host system running the * application) * * To use this class, you should write a new class that inherits from it, and override the * onDeviceConnected method. Once you instantiate your class, use the * OpenNI::addDeviceConnectedListener() function to add your listener object to OpenNI's list of listeners. Your * handler function will then be called whenever the event occurs. A OpenNI::removeDeviceConnectedListener() * function is also provided, if you want to have your class stop listening to these events for any * reason. */ class DeviceConnectedListener { public: DeviceConnectedListener() { m_deviceConnectedCallbacks.deviceConnected = deviceConnectedCallback; m_deviceConnectedCallbacks.deviceDisconnected = NULL; m_deviceConnectedCallbacks.deviceStateChanged = NULL; m_deviceConnectedCallbacksHandle = NULL; } virtual ~DeviceConnectedListener() { } /** * Callback function for the onDeviceConnected event. This function will be * called whenever this event occurs. When this happens, a pointer to the @ref DeviceInfo * object for the newly connected device will be supplied. Note that once a * device is removed, if it was opened by a @ref Device object, that object can no longer be * used to access the device, even if it was reconnected. Once a device was reconnected, * @ref Device::open() should be called again in order to use this device. * * If you wish to open the new device as it is connected, simply query the provided DeviceInfo * object to obtain the URI of the device, and pass this URI to the Device.Open() function. */ virtual void onDeviceConnected(const DeviceInfo*) = 0; private: static void ONI_CALLBACK_TYPE deviceConnectedCallback(const OniDeviceInfo* pInfo, void* pCookie) { DeviceConnectedListener* pListener = (DeviceConnectedListener*)pCookie; pListener->onDeviceConnected(static_cast(pInfo)); } friend class OpenNI; OniDeviceCallbacks m_deviceConnectedCallbacks; OniCallbackHandle m_deviceConnectedCallbacksHandle; }; /** * The OpenNI::DeviceDisconnectedListener class provides a means of registering for, and responding to * when a device is disconnected. * * onDeviceDisconnected is called when a device is removed from the system. Note that once a * device is removed, if it was opened by a @ref Device object, that object can no longer be * used to access the device, even if it was reconnected. Once a device was reconnected, * @ref Device::open() should be called again in order to use this device. * * To use this class, you should write a new class that inherits from it, and override the * onDeviceDisconnected method. Once you instantiate your class, use the * OpenNI::addDeviceDisconnectedListener() function to add your listener object to OpenNI's list of listeners. Your * handler function will then be called whenever the event occurs. A OpenNI::removeDeviceDisconnectedListener() * function is also provided, if you want to have your class stop listening to these events for any * reason. */ class DeviceDisconnectedListener { public: DeviceDisconnectedListener() { m_deviceDisconnectedCallbacks.deviceConnected = NULL; m_deviceDisconnectedCallbacks.deviceDisconnected = deviceDisconnectedCallback; m_deviceDisconnectedCallbacks.deviceStateChanged = NULL; m_deviceDisconnectedCallbacksHandle = NULL; } virtual ~DeviceDisconnectedListener() { } /** * Callback function for the onDeviceDisconnected event. This function will be * called whenever this event occurs. When this happens, a pointer to the DeviceInfo * object for the newly disconnected device will be supplied. Note that once a * device is removed, if it was opened by a @ref Device object, that object can no longer be * used to access the device, even if it was reconnected. Once a device was reconnected, * @ref Device::open() should be called again in order to use this device. */ virtual void onDeviceDisconnected(const DeviceInfo*) = 0; private: static void ONI_CALLBACK_TYPE deviceDisconnectedCallback(const OniDeviceInfo* pInfo, void* pCookie) { DeviceDisconnectedListener* pListener = (DeviceDisconnectedListener*)pCookie; pListener->onDeviceDisconnected(static_cast(pInfo)); } friend class OpenNI; OniDeviceCallbacks m_deviceDisconnectedCallbacks; OniCallbackHandle m_deviceDisconnectedCallbacksHandle; }; /** * The OpenNI::DeviceStateChangedListener class provides a means of registering for, and responding to * when a device's state is changed. * * onDeviceStateChanged is triggered whenever the state of a connected device is changed. * * To use this class, you should write a new class that inherits from it, and override the * onDeviceStateChanged method. Once you instantiate your class, use the * OpenNI::addDeviceStateChangedListener() function to add your listener object to OpenNI's list of listeners. Your * handler function will then be called whenever the event occurs. A OpenNI::removeDeviceStateChangedListener() * function is also provided, if you want to have your class stop listening to these events for any * reason. */ class DeviceStateChangedListener { public: DeviceStateChangedListener() { m_deviceStateChangedCallbacks.deviceConnected = NULL; m_deviceStateChangedCallbacks.deviceDisconnected = NULL; m_deviceStateChangedCallbacks.deviceStateChanged = deviceStateChangedCallback; m_deviceStateChangedCallbacksHandle = NULL; } virtual ~DeviceStateChangedListener() { } /** * Callback function for the onDeviceStateChanged event. This function will be * called whenever this event occurs. When this happens, a pointer to a DeviceInfo * object for the affected device will be supplied, as well as the new DeviceState * value of that device. */ virtual void onDeviceStateChanged(const DeviceInfo*, DeviceState) = 0; private: static void ONI_CALLBACK_TYPE deviceStateChangedCallback(const OniDeviceInfo* pInfo, OniDeviceState state, void* pCookie) { DeviceStateChangedListener* pListener = (DeviceStateChangedListener*)pCookie; pListener->onDeviceStateChanged(static_cast(pInfo), DeviceState(state)); } friend class OpenNI; OniDeviceCallbacks m_deviceStateChangedCallbacks; OniCallbackHandle m_deviceStateChangedCallbacksHandle; }; /** Initialize the library. This will load all available drivers, and see which devices are available It is forbidden to call any other method in OpenNI before calling @ref initialize(). */ static Status initialize() { return (Status)oniInitialize(ONI_API_VERSION); // provide version of API, to make sure proper struct sizes are used } /** Stop using the library. Unload all drivers, close all streams and devices. Once @ref shutdown was called, no other calls to OpenNI is allowed. */ static void shutdown() { oniShutdown(); } /** * Returns the version of OpenNI */ static Version getVersion() { OniVersion oniVersion = oniGetVersion(); Version version; version.major = oniVersion.major; version.minor = oniVersion.minor; version.maintenance = oniVersion.maintenance; version.build = oniVersion.build; return version; } /** * Retrieves the calling thread's last extended error information. The last extended error information is maintained * on a per-thread basis. Multiple threads do not overwrite each other's last extended error information. * * The extended error information is cleared on every call to an OpenNI method, so you should call this method * immediately after a call to an OpenNI method which have failed. */ static const char* getExtendedError() { return oniGetExtendedError(); } /** Fills up an array of @ref DeviceInfo objects with devices that are available. @param [in,out] deviceInfoList An array to be filled with devices. */ static void enumerateDevices(Array* deviceInfoList) { OniDeviceInfo* m_pDeviceInfos; int m_deviceInfoCount; oniGetDeviceList(&m_pDeviceInfos, &m_deviceInfoCount); deviceInfoList->_setData((DeviceInfo*)m_pDeviceInfos, m_deviceInfoCount, true); oniReleaseDeviceList(m_pDeviceInfos); } /** Wait for a new frame from any of the streams provided. The function blocks until any of the streams has a new frame available, or the timeout has passed. @param [in] pStreams An array of streams to wait for. @param [in] streamCount The number of streams in @c pStreams @param [out] pReadyStreamIndex The index of the first stream that has new frame available. @param [in] timeout [Optional] A timeout before returning if no stream has new data. Default value is @ref TIMEOUT_FOREVER. */ static Status waitForAnyStream(VideoStream** pStreams, int streamCount, int* pReadyStreamIndex, int timeout = TIMEOUT_FOREVER) { static const int ONI_MAX_STREAMS = 50; OniStreamHandle streams[ONI_MAX_STREAMS]; if (streamCount > ONI_MAX_STREAMS) { printf("Too many streams for wait: %d > %d\n", streamCount, ONI_MAX_STREAMS); return STATUS_BAD_PARAMETER; } *pReadyStreamIndex = -1; for (int i = 0; i < streamCount; ++i) { if (pStreams[i] != NULL) { streams[i] = pStreams[i]->_getHandle(); } else { streams[i] = NULL; } } Status rc = (Status)oniWaitForAnyStream(streams, streamCount, pReadyStreamIndex, timeout); return rc; } /** * Add a listener to the list of objects that receive the event when a device is connected. See the * @ref OpenNI::DeviceConnectedListener class for details on utilizing the events provided by OpenNI. * * @param pListener Pointer to the Listener to be added to the list * @returns Status code indicating success or failure of this operation. */ static Status addDeviceConnectedListener(DeviceConnectedListener* pListener) { if (pListener->m_deviceConnectedCallbacksHandle != NULL) { return STATUS_ERROR; } return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceConnectedCallbacks, pListener, &pListener->m_deviceConnectedCallbacksHandle); } /** * Add a listener to the list of objects that receive the event when a device is disconnected. See the * @ref OpenNI::DeviceDisconnectedListener class for details on utilizing the events provided by OpenNI. * * @param pListener Pointer to the Listener to be added to the list * @returns Status code indicating success or failure of this operation. */ static Status addDeviceDisconnectedListener(DeviceDisconnectedListener* pListener) { if (pListener->m_deviceDisconnectedCallbacksHandle != NULL) { return STATUS_ERROR; } return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceDisconnectedCallbacks, pListener, &pListener->m_deviceDisconnectedCallbacksHandle); } /** * Add a listener to the list of objects that receive the event when a device's state changes. See the * @ref OpenNI::DeviceStateChangedListener class for details on utilizing the events provided by OpenNI. * * @param pListener Pointer to the Listener to be added to the list * @returns Status code indicating success or failure of this operation. */ static Status addDeviceStateChangedListener(DeviceStateChangedListener* pListener) { if (pListener->m_deviceStateChangedCallbacksHandle != NULL) { return STATUS_ERROR; } return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceStateChangedCallbacks, pListener, &pListener->m_deviceStateChangedCallbacksHandle); } /** * Remove a listener from the list of objects that receive the event when a device is connected. See * the @ref OpenNI::DeviceConnectedListener class for details on utilizing the events provided by OpenNI. * * @param pListener Pointer to the Listener to be removed from the list * @returns Status code indicating the success or failure of this operation. */ static void removeDeviceConnectedListener(DeviceConnectedListener* pListener) { oniUnregisterDeviceCallbacks(pListener->m_deviceConnectedCallbacksHandle); pListener->m_deviceConnectedCallbacksHandle = NULL; } /** * Remove a listener from the list of objects that receive the event when a device is disconnected. See * the @ref OpenNI::DeviceDisconnectedListener class for details on utilizing the events provided by OpenNI. * * @param pListener Pointer to the Listener to be removed from the list * @returns Status code indicating the success or failure of this operation. */ static void removeDeviceDisconnectedListener(DeviceDisconnectedListener* pListener) { oniUnregisterDeviceCallbacks(pListener->m_deviceDisconnectedCallbacksHandle); pListener->m_deviceDisconnectedCallbacksHandle = NULL; } /** * Remove a listener from the list of objects that receive the event when a device's state changes. See * the @ref OpenNI::DeviceStateChangedListener class for details on utilizing the events provided by OpenNI. * * @param pListener Pointer to the Listener to be removed from the list * @returns Status code indicating the success or failure of this operation. */ static void removeDeviceStateChangedListener(DeviceStateChangedListener* pListener) { oniUnregisterDeviceCallbacks(pListener->m_deviceStateChangedCallbacksHandle); pListener->m_deviceStateChangedCallbacksHandle = NULL; } /** * Change the log output folder * @param const char * strLogOutputFolder [in] log required folder * * @retval STATUS_OK Upon successful completion. * @retval STATUS_ERROR Upon any kind of failure. */ static Status setLogOutputFolder(const char *strLogOutputFolder) { return (Status)oniSetLogOutputFolder(strLogOutputFolder); } /** * Get current log file name * @param char * strFileName [out] returned file name buffer * @param int nBufferSize [in] Buffer size * * @retval STATUS_OK Upon successful completion. * @retval STATUS_ERROR Upon any kind of failure. */ static Status getLogFileName(char *strFileName, int nBufferSize) { return (Status)oniGetLogFileName(strFileName, nBufferSize); } /** * Set minimum severity for log produce * @param const char * strMask [in] Logger name * @param int nMinSeverity [in] Logger severity * * @retval STATUS_OK Upon successful completion. * @retval STATUS_ERROR Upon any kind of failure. */ static Status setLogMinSeverity(int nMinSeverity) { return(Status) oniSetLogMinSeverity(nMinSeverity); } /** * Configures if log entries will be printed to console. * @param const OniBool bConsoleOutput [in] TRUE to print log entries to console, FALSE otherwise. * * @retval STATUS_OK Upon successful completion. * @retval STATUS_ERROR Upon any kind of failure. */ static Status setLogConsoleOutput(bool bConsoleOutput) { return (Status)oniSetLogConsoleOutput(bConsoleOutput); } /** * Configures if log entries will be printed to file. * @param const OniBool bConsoleOutput [in] TRUE to print log entries to file, FALSE otherwise. * * @retval STATUS_OK Upon successful completion. * @retval STATUS_ERROR Upon any kind of failure. */ static Status setLogFileOutput(bool bFileOutput) { return (Status)oniSetLogFileOutput(bFileOutput); } #if ONI_PLATFORM == ONI_PLATFORM_ANDROID_ARM /** * Configures if log entries will be printed to the Android log. * @param OniBool bAndroidOutput bAndroidOutput [in] TRUE to print log entries to the Android log, FALSE otherwise. * * @retval STATUS_OK Upon successful completion. * @retval STATUS_ERROR Upon any kind of failure. */ static Status setLogAndroidOutput(bool bAndroidOutput) { return (Status)oniSetLogAndroidOutput(bAndroidOutput); } #endif private: OpenNI() { } }; /** The CoordinateConverter class converts points between the different coordinate systems. Depth and World coordinate systems OpenNI applications commonly use two different coordinate systems to represent depth. These two systems are referred to as Depth and World representation. Depth coordinates are the native data representation. In this system, the frame is a map (two dimensional array), and each pixel is assigned a depth value. This depth value represents the distance between the camera plane and whatever object is in the given pixel. The X and Y coordinates are simply the location in the map, where the origin is the top-left corner of the field of view. World coordinates superimpose a more familiar 3D Cartesian coordinate system on the world, with the camera lens at the origin. In this system, every point is specified by 3 points -- x, y and z. The x axis of this system is along a line that passes through the infrared projector and CMOS imager of the camera. The y axis is parallel to the front face of the camera, and perpendicular to the x axis (it will also be perpendicular to the ground if the camera is upright and level). The z axis runs into the scene, perpendicular to both the x and y axis. From the perspective of the camera, an object moving from left to right is moving along the increasing x axis. An object moving up is moving along the increasing y axis, and an object moving away from the camera is moving along the increasing z axis. Mathematically, the Depth coordinate system is the projection of the scene on the CMOS. If the sensor's angular field of view and resolution are known, then an angular size can be calculated for each pixel. This is how the conversion algorithms work. The dependence of this calculation on FoV and resolution is the reason that a @ref VideoStream pointer must be provided to these functions. The @ref VideoStream pointer is used to determine parameters for the specific points to be converted. Since Depth coordinates are a projective, the apparent size of objects in depth coordinates (measured in pixels) will increase as an object moves closer to the sensor. The size of objects in the World coordinate system is independent of distance from the sensor. Note that converting from Depth to World coordinates is relatively expensive computationally. It is generally not practical to convert the entire raw depth map to World coordinates. A better approach is to have your computer vision algorithm work in Depth coordinates for as long as possible, and only converting a few specific points to World coordinates right before output. Note that when converting from Depth to World or vice versa, the Z value remains the same. */ class CoordinateConverter { public: /** Converts a single point from the World coordinate system to the Depth coordinate system. @param [in] depthStream Reference to an openni::VideoStream that will be used to determine the format of the Depth coordinates @param [in] worldX The X coordinate of the point to be converted, measured in millimeters in World coordinates @param [in] worldY The Y coordinate of the point to be converted, measured in millimeters in World coordinates @param [in] worldZ The Z coordinate of the point to be converted, measured in millimeters in World coordinates @param [out] pDepthX Pointer to a place to store the X coordinate of the output value, measured in pixels with 0 at far left of image @param [out] pDepthY Pointer to a place to store the Y coordinate of the output value, measured in pixels with 0 at top of image @param [out] pDepthZ Pointer to a place to store the Z(depth) coordinate of the output value, measured in the @ref PixelFormat of depthStream */ static Status convertWorldToDepth(const VideoStream& depthStream, float worldX, float worldY, float worldZ, int* pDepthX, int* pDepthY, DepthPixel* pDepthZ) { float depthX, depthY, depthZ; Status rc = (Status)oniCoordinateConverterWorldToDepth(depthStream._getHandle(), worldX, worldY, worldZ, &depthX, &depthY, &depthZ); *pDepthX = (int)depthX; *pDepthY = (int)depthY; *pDepthZ = (DepthPixel)depthZ; return rc; } /** Converts a single point from the World coordinate system to a floating point representation of the Depth coordinate system @param [in] depthStream Reference to an openni::VideoStream that will be used to determine the format of the Depth coordinates @param [in] worldX The X coordinate of the point to be converted, measured in millimeters in World coordinates @param [in] worldY The Y coordinate of the point to be converted, measured in millimeters in World coordinates @param [in] worldZ The Z coordinate of the point to be converted, measured in millimeters in World coordinates @param [out] pDepthX Pointer to a place to store the X coordinate of the output value, measured in pixels with 0.0 at far left of the image @param [out] pDepthY Pointer to a place to store the Y coordinate of the output value, measured in pixels with 0.0 at the top of the image @param [out] pDepthZ Pointer to a place to store the Z(depth) coordinate of the output value, measured in millimeters with 0.0 at the camera lens */ static Status convertWorldToDepth(const VideoStream& depthStream, float worldX, float worldY, float worldZ, float* pDepthX, float* pDepthY, float* pDepthZ) { return (Status)oniCoordinateConverterWorldToDepth(depthStream._getHandle(), worldX, worldY, worldZ, pDepthX, pDepthY, pDepthZ); } /** Converts a single point from the Depth coordinate system to the World coordinate system. @param [in] depthStream Reference to an openi::VideoStream that will be used to determine the format of the Depth coordinates @param [in] depthX The X coordinate of the point to be converted, measured in pixels with 0 at the far left of the image @param [in] depthY The Y coordinate of the point to be converted, measured in pixels with 0 at the top of the image @param [in] depthZ the Z(depth) coordinate of the point to be converted, measured in the @ref PixelFormat of depthStream @param [out] pWorldX Pointer to a place to store the X coordinate of the output value, measured in millimeters in World coordinates @param [out] pWorldY Pointer to a place to store the Y coordinate of the output value, measured in millimeters in World coordinates @param [out] pWorldZ Pointer to a place to store the Z coordinate of the output value, measured in millimeters in World coordinates */ static Status convertDepthToWorld(const VideoStream& depthStream, int depthX, int depthY, DepthPixel depthZ, float* pWorldX, float* pWorldY, float* pWorldZ) { return (Status)oniCoordinateConverterDepthToWorld(depthStream._getHandle(), float(depthX), float(depthY), float(depthZ), pWorldX, pWorldY, pWorldZ); } /** Converts a single point from a floating point representation of the Depth coordinate system to the World coordinate system. @param [in] depthStream Reference to an openi::VideoStream that will be used to determine the format of the Depth coordinates @param [in] depthX The X coordinate of the point to be converted, measured in pixels with 0.0 at the far left of the image @param [in] depthY The Y coordinate of the point to be converted, measured in pixels with 0.0 at the top of the image @param [in] depthZ Z(depth) coordinate of the point to be converted, measured in the @ref PixelFormat of depthStream @param [out] pWorldX Pointer to a place to store the X coordinate of the output value, measured in millimeters in World coordinates @param [out] pWorldY Pointer to a place to store the Y coordinate of the output value, measured in millimeters in World coordinates @param [out] pWorldZ Pointer to a place to store the Z coordinate of the output value, measured in millimeters in World coordinates */ static Status convertDepthToWorld(const VideoStream& depthStream, float depthX, float depthY, float depthZ, float* pWorldX, float* pWorldY, float* pWorldZ) { return (Status)oniCoordinateConverterDepthToWorld(depthStream._getHandle(), depthX, depthY, depthZ, pWorldX, pWorldY, pWorldZ); } /** For a given depth point, provides the coordinates of the corresponding color value. Useful for superimposing the depth and color images. This operation is the same as turning on registration, but is performed on a single pixel rather than the whole image. @param [in] depthStream Reference to a openni::VideoStream that produced the depth value @param [in] colorStream Reference to a openni::VideoStream that we want to find the appropriate color pixel in @param [in] depthX X value of the depth point, given in Depth coordinates and measured in pixels @param [in] depthY Y value of the depth point, given in Depth coordinates and measured in pixels @param [in] depthZ Z(depth) value of the depth point, given in the @ref PixelFormat of depthStream @param [out] pColorX The X coordinate of the color pixel that overlaps the given depth pixel, measured in pixels @param [out] pColorY The Y coordinate of the color pixel that overlaps the given depth pixel, measured in pixels */ static Status convertDepthToColor(const VideoStream& depthStream, const VideoStream& colorStream, int depthX, int depthY, DepthPixel depthZ, int* pColorX, int* pColorY) { return (Status)oniCoordinateConverterDepthToColor(depthStream._getHandle(), colorStream._getHandle(), depthX, depthY, depthZ, pColorX, pColorY); } }; /** * The Recorder class is used to record streams to an ONI file. * * After a recorder is instantiated, it must be initialized with a specific filename where * the recording will be stored. The recorder is then attached to one or more streams. Once * this is complete, the recorder can be told to start recording. The recorder will store * every frame from every stream to the specified file. Later, this file can be used to * initialize a file Device, and used to play back the same data that was recorded. * * Opening a file device is done by passing its path as the uri to the @ref Device::open() method. * * @see PlaybackControl for options available to play a reorded file. * */ class Recorder { public: /** * Creates a recorder. The recorder is not valid, i.e. @ref isValid() returns * false. You must initialize the recorder before use with @ref create(). */ Recorder() : m_recorder(NULL) { } /** * Destroys a recorder. This will also stop recording. */ ~Recorder() { destroy(); } /** * Initializes a recorder. You can initialize the recorder only once. Attempts * to intialize more than once will result in an error code being returned. * * Initialization assigns the recorder to an output file that will be used for * recording. Before use, the @ref attach() function must also be used to assign input * data to the Recorder. * * @param [in] fileName The name of a file which will contain the recording. * @returns Status code which indicates success or failure of the operation. */ Status create(const char* fileName) { if (!isValid()) { return (Status)oniCreateRecorder(fileName, &m_recorder); } return STATUS_ERROR; } /** * Verifies if the recorder is valid, i.e. if one can record with this recorder. A * recorder object is not valid until the @ref create() method is called. * * @returns true if the recorder has been intialized, false otherwise. */ bool isValid() const { return NULL != getHandle(); } /** * Attaches a stream to the recorder. Note, this won't start recording, you * should explicitly start it using @ref start() method. As soon as the recording * process has been started, no more streams can be attached to the recorder. * * @param [in] stream The stream to be recorded. * @param [in] allowLossyCompression [Optional] If this value is true, the recorder might use * a lossy compression, which means that when the recording will be played-back, there might * be small differences from the original frame. Default value is false. */ Status attach(VideoStream& stream, bool allowLossyCompression = false) { if (!isValid() || !stream.isValid()) { return STATUS_ERROR; } return (Status)oniRecorderAttachStream( m_recorder, stream._getHandle(), allowLossyCompression); } /** * Starts recording. * Once this method is called, the recorder will take all subsequent frames from the attached streams * and store them in the file. * You may not attach additional streams once recording was started. */ Status start() { if (!isValid()) { return STATUS_ERROR; } return (Status)oniRecorderStart(m_recorder); } /** * Stops recording. You may use @ref start() to resume the recording. */ void stop() { if (isValid()) { oniRecorderStop(m_recorder); } } /** Destroys the recorder object. */ void destroy() { if (isValid()) { oniRecorderDestroy(&m_recorder); } } private: Recorder(const Recorder&); Recorder& operator=(const Recorder&); /** * Returns a handle of this recorder. */ OniRecorderHandle getHandle() const { return m_recorder; } OniRecorderHandle m_recorder; }; // Implemetation Status VideoStream::create(const Device& device, SensorType sensorType) { OniStreamHandle streamHandle; Status rc = (Status)oniDeviceCreateStream(device._getHandle(), (OniSensorType)sensorType, &streamHandle); if (rc != STATUS_OK) { return rc; } m_isOwner = true; _setHandle(streamHandle); if (isPropertySupported(STREAM_PROPERTY_AUTO_WHITE_BALANCE) && isPropertySupported(STREAM_PROPERTY_AUTO_EXPOSURE)) { m_pCameraSettings = new CameraSettings(this); } return STATUS_OK; } void VideoStream::destroy() { if (!isValid()) { return; } if (m_pCameraSettings != NULL) { delete m_pCameraSettings; m_pCameraSettings = NULL; } if (m_stream != NULL) { if(m_isOwner) oniStreamDestroy(m_stream); m_stream = NULL; } } Status Device::open(const char* uri) { //If we are not the owners, we stick with our own device if(!m_isOwner) { if(isValid()){ return STATUS_OK; }else{ return STATUS_OUT_OF_FLOW; } } OniDeviceHandle deviceHandle; Status rc = (Status)oniDeviceOpen(uri, &deviceHandle); if (rc != STATUS_OK) { return rc; } _setHandle(deviceHandle); return STATUS_OK; } Status Device::_openEx(const char* uri, const char* mode) { //If we are not the owners, we stick with our own device if(!m_isOwner) { if(isValid()){ return STATUS_OK; }else{ return STATUS_OUT_OF_FLOW; } } OniDeviceHandle deviceHandle; Status rc = (Status)oniDeviceOpenEx(uri, mode, &deviceHandle); if (rc != STATUS_OK) { return rc; } _setHandle(deviceHandle); return STATUS_OK; } Status Device::_setHandle(OniDeviceHandle deviceHandle) { if (m_device == NULL) { m_device = deviceHandle; clearSensors(); oniDeviceGetInfo(m_device, &m_deviceInfo); if (isFile()) { m_pPlaybackControl = new PlaybackControl(this); } // Read deviceInfo return STATUS_OK; } return STATUS_OUT_OF_FLOW; } void Device::close() { if (m_pPlaybackControl != NULL) { delete m_pPlaybackControl; m_pPlaybackControl = NULL; } if (m_device != NULL) { if(m_isOwner) { oniDeviceClose(m_device); } m_device = NULL; } } } #endif // _OPEN_NI_HPP_ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/PS1080.h000066400000000000000000000472661264163024100275570ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _PS1080_H_ #define _PS1080_H_ #include /** The maximum permitted Xiron device name string length. */ #define XN_DEVICE_MAX_STRING_LENGTH 200 /* * private properties of PS1080 devices. * * @remarks * properties structure is 0x1080XXYY where XX is range and YY is code. * range values: * F0 - device properties * E0 - device commands * 00 - common stream properties * 10 - depth stream properties * 20 - color stream properties */ enum { /*******************************************************************/ /* Device properties */ /*******************************************************************/ /** unsigned long long (XnSensorUsbInterface) */ XN_MODULE_PROPERTY_USB_INTERFACE = 0x1080F001, // "UsbInterface" /** Boolean */ XN_MODULE_PROPERTY_MIRROR = 0x1080F002, // "Mirror" /** unsigned long long, get only */ XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP = 0x1080F004, // "ResetSensorOnStartup" /** unsigned long long, get only */ XN_MODULE_PROPERTY_LEAN_INIT = 0x1080F005, // "LeanInit" /** char[XN_DEVICE_MAX_STRING_LENGTH], get only */ XN_MODULE_PROPERTY_SERIAL_NUMBER = 0x1080F006, // "ID" /** XnVersions, get only */ XN_MODULE_PROPERTY_VERSION = 0x1080F007, // "Version" /** Boolean */ XN_MODULE_PROPERTY_FIRMWARE_FRAME_SYNC = 0x1080F008, /** Boolean */ XN_MODULE_PROPERTY_HOST_TIMESTAMPS = 0x1080FF77, // "HostTimestamps" /** Boolean */ XN_MODULE_PROPERTY_CLOSE_STREAMS_ON_SHUTDOWN = 0x1080FF78, // "CloseStreamsOnShutdown" /** Integer */ XN_MODULE_PROPERTY_FIRMWARE_LOG_INTERVAL = 0x1080FF7F, // "FirmwareLogInterval" /** Boolean */ XN_MODULE_PROPERTY_PRINT_FIRMWARE_LOG = 0x1080FF80, // "FirmwareLogPrint" /** Integer */ XN_MODULE_PROPERTY_FIRMWARE_LOG_FILTER = 0x1080FF81, // "FirmwareLogFilter" /** String, get only */ XN_MODULE_PROPERTY_FIRMWARE_LOG = 0x1080FF82, // "FirmwareLog" /** Integer */ XN_MODULE_PROPERTY_FIRMWARE_CPU_INTERVAL = 0x1080FF83, // "FirmwareCPUInterval" /** String, get only */ XN_MODULE_PROPERTY_PHYSICAL_DEVICE_NAME = 0x1080FF7A, // "PhysicalDeviceName" /** String, get only */ XN_MODULE_PROPERTY_VENDOR_SPECIFIC_DATA = 0x1080FF7B, // "VendorSpecificData" /** String, get only */ XN_MODULE_PROPERTY_SENSOR_PLATFORM_STRING = 0x1080FF7C, // "SensorPlatformString" /*******************************************************************/ /* Device commands (activated via SetProperty/GetProperty) */ /*******************************************************************/ /** XnInnerParam */ XN_MODULE_PROPERTY_FIRMWARE_PARAM = 0x1080E001, // "FirmwareParam" /** unsigned long long, set only */ XN_MODULE_PROPERTY_RESET = 0x1080E002, // "Reset" /** XnControlProcessingData */ XN_MODULE_PROPERTY_IMAGE_CONTROL = 0x1080E003, // "ImageControl" /** XnControlProcessingData */ XN_MODULE_PROPERTY_DEPTH_CONTROL = 0x1080E004, // "DepthControl" /** XnAHBData */ XN_MODULE_PROPERTY_AHB = 0x1080E005, // "AHB" /** XnLedState */ XN_MODULE_PROPERTY_LED_STATE = 0x1080E006, // "LedState" /** Boolean */ XN_MODULE_PROPERTY_EMITTER_STATE = 0x1080E007, // "EmitterState" /** XnCmosBlankingUnits */ XN_MODULE_PROPERTY_CMOS_BLANKING_UNITS = 0x1080FF74, // "CmosBlankingUnits" /** XnCmosBlankingTime */ XN_MODULE_PROPERTY_CMOS_BLANKING_TIME = 0x1080FF75, // "CmosBlankingTime" /** XnFlashFileList, get only */ XN_MODULE_PROPERTY_FILE_LIST = 0x1080FF84, // "FileList" /** XnParamFlashData, get only */ XN_MODULE_PROPERTY_FLASH_CHUNK = 0x1080FF85, // "FlashChunk" XN_MODULE_PROPERTY_FILE = 0x1080FF86, // "FlashFile" /** Integer */ XN_MODULE_PROPERTY_DELETE_FILE = 0x1080FF87, // "DeleteFile" XN_MODULE_PROPERTY_FILE_ATTRIBUTES = 0x1080FF88, // "FileAttributes" XN_MODULE_PROPERTY_TEC_SET_POINT = 0x1080FF89, // "TecSetPoint" /** get only */ XN_MODULE_PROPERTY_TEC_STATUS = 0x1080FF8A, // "TecStatus" /** get only */ XN_MODULE_PROPERTY_TEC_FAST_CONVERGENCE_STATUS = 0x1080FF8B, // "TecFastConvergenceStatus" XN_MODULE_PROPERTY_EMITTER_SET_POINT = 0x1080FF8C, // "EmitterSetPoint" /** get only */ XN_MODULE_PROPERTY_EMITTER_STATUS = 0x1080FF8D, // "EmitterStatus" XN_MODULE_PROPERTY_I2C = 0x1080FF8E, // "I2C" /** Integer, set only */ XN_MODULE_PROPERTY_BIST = 0x1080FF8F, // "BIST" /** XnProjectorFaultData, set only */ XN_MODULE_PROPERTY_PROJECTOR_FAULT = 0x1080FF90, // "ProjectorFault" /** Boolean, set only */ XN_MODULE_PROPERTY_APC_ENABLED = 0x1080FF91, // "APCEnabled" /** Boolean */ XN_MODULE_PROPERTY_FIRMWARE_TEC_DEBUG_PRINT = 0x1080FF92, // "TecDebugPrint" /*******************************************************************/ /* Common stream properties */ /*******************************************************************/ /** unsigned long long */ XN_STREAM_PROPERTY_INPUT_FORMAT = 0x10800001, // "InputFormat" /** unsigned long long (XnCroppingMode) */ XN_STREAM_PROPERTY_CROPPING_MODE = 0x10800002, // "CroppingMode" /*******************************************************************/ /* Depth stream properties */ /*******************************************************************/ /** unsigned long long */ XN_STREAM_PROPERTY_CLOSE_RANGE = 0x1080F003, // "CloseRange" /** XnPixelRegistration - get only */ XN_STREAM_PROPERTY_PIXEL_REGISTRATION = 0x10801001, // "PixelRegistration" /** unsigned long long */ XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED = 0x10801002, // "WhiteBalancedEnabled" /** unsigned long long */ XN_STREAM_PROPERTY_GAIN = 0x10801003, // "Gain" /** unsigned long long */ XN_STREAM_PROPERTY_HOLE_FILTER = 0x10801004, // "HoleFilter" /** unsigned long long (XnProcessingType) */ XN_STREAM_PROPERTY_REGISTRATION_TYPE = 0x10801005, // "RegistrationType" /** XnDepthAGCBin* */ XN_STREAM_PROPERTY_AGC_BIN = 0x10801006, // "AGCBin" /** unsigned long long, get only */ XN_STREAM_PROPERTY_CONST_SHIFT = 0x10801007, // "ConstShift" /** unsigned long long, get only */ XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR = 0x10801008, // "PixelSizeFactor" /** unsigned long long, get only */ XN_STREAM_PROPERTY_MAX_SHIFT = 0x10801009, // "MaxShift" /** unsigned long long, get only */ XN_STREAM_PROPERTY_PARAM_COEFF = 0x1080100A, // "ParamCoeff" /** unsigned long long, get only */ XN_STREAM_PROPERTY_SHIFT_SCALE = 0x1080100B, // "ShiftScale" /** unsigned long long, get only */ XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE = 0x1080100C, // "ZPD" /** double, get only */ XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE = 0x1080100D, // "ZPPS" /** double, get only */ XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE = 0x1080100E, // "LDDIS" /** double, get only */ XN_STREAM_PROPERTY_DCMOS_RCMOS_DISTANCE = 0x1080100F, // "DCRCDIS" /** OniDepthPixel[], get only */ XN_STREAM_PROPERTY_S2D_TABLE = 0x10801010, // "S2D" /** unsigned short[], get only */ XN_STREAM_PROPERTY_D2S_TABLE = 0x10801011, // "D2S" /** get only */ XN_STREAM_PROPERTY_DEPTH_SENSOR_CALIBRATION_INFO = 0x10801012, /** Boolean */ XN_STREAM_PROPERTY_GMC_MODE = 0x1080FF44, // "GmcMode" /** Boolean */ XN_STREAM_PROPERTY_GMC_DEBUG = 0x1080FF45, // "GmcDebug" /** Boolean */ XN_STREAM_PROPERTY_WAVELENGTH_CORRECTION = 0x1080FF46, // "WavelengthCorrection" /** Boolean */ XN_STREAM_PROPERTY_WAVELENGTH_CORRECTION_DEBUG = 0x1080FF47, // "WavelengthCorrectionDebug" /*******************************************************************/ /* Color stream properties */ /*******************************************************************/ /** Integer */ XN_STREAM_PROPERTY_FLICKER = 0x10802001, // "Flicker" }; typedef enum { XN_SENSOR_FW_VER_UNKNOWN = 0, XN_SENSOR_FW_VER_0_17 = 1, XN_SENSOR_FW_VER_1_1 = 2, XN_SENSOR_FW_VER_1_2 = 3, XN_SENSOR_FW_VER_3_0 = 4, XN_SENSOR_FW_VER_4_0 = 5, XN_SENSOR_FW_VER_5_0 = 6, XN_SENSOR_FW_VER_5_1 = 7, XN_SENSOR_FW_VER_5_2 = 8, XN_SENSOR_FW_VER_5_3 = 9, XN_SENSOR_FW_VER_5_4 = 10, XN_SENSOR_FW_VER_5_5 = 11, XN_SENSOR_FW_VER_5_6 = 12, XN_SENSOR_FW_VER_5_7 = 13, XN_SENSOR_FW_VER_5_8 = 14, } XnFWVer; typedef enum { XN_SENSOR_VER_UNKNOWN = 0, XN_SENSOR_VER_2_0 = 1, XN_SENSOR_VER_3_0 = 2, XN_SENSOR_VER_4_0 = 3, XN_SENSOR_VER_5_0 = 4 } XnSensorVer; typedef enum { XN_SENSOR_HW_VER_UNKNOWN = 0, XN_SENSOR_HW_VER_FPDB_10 = 1, XN_SENSOR_HW_VER_CDB_10 = 2, XN_SENSOR_HW_VER_RD_3 = 3, XN_SENSOR_HW_VER_RD_5 = 4, XN_SENSOR_HW_VER_RD1081 = 5, XN_SENSOR_HW_VER_RD1082 = 6, XN_SENSOR_HW_VER_RD109 = 7 } XnHWVer; typedef enum { XN_SENSOR_CHIP_VER_UNKNOWN = 0, XN_SENSOR_CHIP_VER_PS1000 = 1, XN_SENSOR_CHIP_VER_PS1080 = 2, XN_SENSOR_CHIP_VER_PS1080A6 = 3 } XnChipVer; typedef enum { XN_CMOS_TYPE_IMAGE = 0, XN_CMOS_TYPE_DEPTH = 1, XN_CMOS_COUNT } XnCMOSType; typedef enum { XN_IO_IMAGE_FORMAT_BAYER = 0, XN_IO_IMAGE_FORMAT_YUV422 = 1, XN_IO_IMAGE_FORMAT_JPEG = 2, XN_IO_IMAGE_FORMAT_JPEG_420 = 3, XN_IO_IMAGE_FORMAT_JPEG_MONO = 4, XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422 = 5, XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER = 6, XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUYV = 7, } XnIOImageFormats; typedef enum { XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT = 0, XN_IO_DEPTH_FORMAT_COMPRESSED_PS = 1, XN_IO_DEPTH_FORMAT_UNCOMPRESSED_10_BIT = 2, XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT = 3, XN_IO_DEPTH_FORMAT_UNCOMPRESSED_12_BIT = 4, } XnIODepthFormats; typedef enum { XN_RESET_TYPE_POWER = 0, XN_RESET_TYPE_SOFT = 1, XN_RESET_TYPE_SOFT_FIRST = 2, } XnParamResetType; typedef enum XnSensorUsbInterface { XN_SENSOR_USB_INTERFACE_DEFAULT = 0, XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS = 1, XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS = 2, XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS_LOW_DEPTH = 3, } XnSensorUsbInterface; typedef enum XnProcessingType { XN_PROCESSING_DONT_CARE = 0, XN_PROCESSING_HARDWARE = 1, XN_PROCESSING_SOFTWARE = 2, } XnProcessingType; typedef enum XnCroppingMode { XN_CROPPING_MODE_NORMAL = 1, XN_CROPPING_MODE_INCREASED_FPS = 2, XN_CROPPING_MODE_SOFTWARE_ONLY = 3, } XnCroppingMode; enum { XN_ERROR_STATE_OK = 0, XN_ERROR_STATE_DEVICE_PROJECTOR_FAULT = 1, XN_ERROR_STATE_DEVICE_OVERHEAT = 2, }; typedef enum XnFirmwareCroppingMode { XN_FIRMWARE_CROPPING_MODE_DISABLED = 0, XN_FIRMWARE_CROPPING_MODE_NORMAL = 1, XN_FIRMWARE_CROPPING_MODE_INCREASED_FPS = 2, } XnFirmwareCroppingMode; typedef enum { XnLogFilterDebug = 0x0001, XnLogFilterInfo = 0x0002, XnLogFilterError = 0x0004, XnLogFilterProtocol = 0x0008, XnLogFilterAssert = 0x0010, XnLogFilterConfig = 0x0020, XnLogFilterFrameSync = 0x0040, XnLogFilterAGC = 0x0080, XnLogFilterTelems = 0x0100, XnLogFilterAll = 0xFFFF } XnLogFilter; typedef enum { XnFileAttributeReadOnly = 0x8000 } XnFilePossibleAttributes; typedef enum { XnFlashFileTypeFileTable = 0x00, XnFlashFileTypeScratchFile = 0x01, XnFlashFileTypeBootSector = 0x02, XnFlashFileTypeBootManager = 0x03, XnFlashFileTypeCodeDownloader = 0x04, XnFlashFileTypeMonitor = 0x05, XnFlashFileTypeApplication = 0x06, XnFlashFileTypeFixedParams = 0x07, XnFlashFileTypeDescriptors = 0x08, XnFlashFileTypeDefaultParams = 0x09, XnFlashFileTypeImageCmos = 0x0A, XnFlashFileTypeDepthCmos = 0x0B, XnFlashFileTypeAlgorithmParams = 0x0C, XnFlashFileTypeReferenceQVGA = 0x0D, XnFlashFileTypeReferenceVGA = 0x0E, XnFlashFileTypeMaintenance = 0x0F, XnFlashFileTypeDebugParams = 0x10, XnFlashFileTypePrimeProcessor = 0x11, XnFlashFileTypeGainControl = 0x12, XnFlashFileTypeRegistartionParams = 0x13, XnFlashFileTypeIDParams = 0x14, XnFlashFileTypeSensorTECParams = 0x15, XnFlashFileTypeSensorAPCParams = 0x16, XnFlashFileTypeSensorProjectorFaultParams = 0x17, XnFlashFileTypeProductionFile = 0x18, XnFlashFileTypeUpgradeInProgress = 0x19, XnFlashFileTypeWavelengthCorrection = 0x1A, XnFlashFileTypeGMCReferenceOffset = 0x1B, XnFlashFileTypeSensorNESAParams = 0x1C, XnFlashFileTypeSensorFault = 0x1D, XnFlashFileTypeVendorData = 0x1E, } XnFlashFileType; typedef enum XnBistType { //Auto tests XN_BIST_IMAGE_CMOS = 1 << 0, XN_BIST_IR_CMOS = 1 << 1, XN_BIST_POTENTIOMETER = 1 << 2, XN_BIST_FLASH = 1 << 3, XN_BIST_FULL_FLASH = 1 << 4, XN_BIST_PROJECTOR_TEST_MASK = 1 << 5, XN_BIST_TEC_TEST_MASK = 1 << 6, // Manual tests XN_BIST_NESA_TEST_MASK = 1 << 7, XN_BIST_NESA_UNLIMITED_TEST_MASK = 1 << 8, // Mask of all the auto tests XN_BIST_ALL = (0xFFFFFFFF & ~XN_BIST_NESA_TEST_MASK & ~XN_BIST_NESA_UNLIMITED_TEST_MASK), } XnBistType; typedef enum XnBistError { XN_BIST_RAM_TEST_FAILURE = 1 << 0, XN_BIST_IR_CMOS_CONTROL_BUS_FAILURE = 1 << 1, XN_BIST_IR_CMOS_DATA_BUS_FAILURE = 1 << 2, XN_BIST_IR_CMOS_BAD_VERSION = 1 << 3, XN_BIST_IR_CMOS_RESET_FAILUE = 1 << 4, XN_BIST_IR_CMOS_TRIGGER_FAILURE = 1 << 5, XN_BIST_IR_CMOS_STROBE_FAILURE = 1 << 6, XN_BIST_COLOR_CMOS_CONTROL_BUS_FAILURE = 1 << 7, XN_BIST_COLOR_CMOS_DATA_BUS_FAILURE = 1 << 8, XN_BIST_COLOR_CMOS_BAD_VERSION = 1 << 9, XN_BIST_COLOR_CMOS_RESET_FAILUE = 1 << 10, XN_BIST_FLASH_WRITE_LINE_FAILURE = 1 << 11, XN_BIST_FLASH_TEST_FAILURE = 1 << 12, XN_BIST_POTENTIOMETER_CONTROL_BUS_FAILURE = 1 << 13, XN_BIST_POTENTIOMETER_FAILURE = 1 << 14, XN_BIST_AUDIO_TEST_FAILURE = 1 << 15, XN_BIST_PROJECTOR_TEST_LD_FAIL = 1 << 16, XN_BIST_PROJECTOR_TEST_LD_FAILSAFE_TRIG_FAIL = 1 << 17, XN_BIST_PROJECTOR_TEST_FAILSAFE_HIGH_FAIL = 1 << 18, XN_BIST_PROJECTOR_TEST_FAILSAFE_LOW_FAIL = 1 << 19, XN_TEC_TEST_HEATER_CROSSED = 1 << 20, XN_TEC_TEST_HEATER_DISCONNETED = 1 << 21, XN_TEC_TEST_TEC_CROSSED = 1 << 22, XN_TEC_TEST_TEC_FAULT = 1 << 23, } XnBistError; typedef enum XnDepthCMOSType { XN_DEPTH_CMOS_NONE = 0, XN_DEPTH_CMOS_MT9M001 = 1, XN_DEPTH_CMOS_AR130 = 2, } XnDepthCMOSType; typedef enum XnImageCMOSType { XN_IMAGE_CMOS_NONE = 0, XN_IMAGE_CMOS_MT9M112 = 1, XN_IMAGE_CMOS_MT9D131 = 2, XN_IMAGE_CMOS_MT9M114 = 3, } XnImageCMOSType; #define XN_IO_MAX_I2C_BUFFER_SIZE 10 #define XN_MAX_LOG_SIZE (6*1024) #pragma pack (push, 1) typedef struct XnSDKVersion { unsigned char nMajor; unsigned char nMinor; unsigned char nMaintenance; unsigned short nBuild; } XnSDKVersion; typedef struct { unsigned char nMajor; unsigned char nMinor; unsigned short nBuild; unsigned int nChip; unsigned short nFPGA; unsigned short nSystemVersion; XnSDKVersion SDK; XnHWVer HWVer; XnFWVer FWVer; XnSensorVer SensorVer; XnChipVer ChipVer; } XnVersions; typedef struct { unsigned short nParam; unsigned short nValue; } XnInnerParamData; typedef struct XnDepthAGCBin { unsigned short nBin; unsigned short nMin; unsigned short nMax; } XnDepthAGCBin; typedef struct XnControlProcessingData { unsigned short nRegister; unsigned short nValue; } XnControlProcessingData; typedef struct XnAHBData { unsigned int nRegister; unsigned int nValue; unsigned int nMask; } XnAHBData; typedef struct XnPixelRegistration { unsigned int nDepthX; unsigned int nDepthY; uint16_t nDepthValue; unsigned int nImageXRes; unsigned int nImageYRes; unsigned int nImageX; // out unsigned int nImageY; // out } XnPixelRegistration; typedef struct XnLedState { uint16_t nLedID; uint16_t nState; } XnLedState; typedef struct XnCmosBlankingTime { XnCMOSType nCmosID; float nTimeInMilliseconds; uint16_t nNumberOfFrames; } XnCmosBlankingTime; typedef struct XnCmosBlankingUnits { XnCMOSType nCmosID; uint16_t nUnits; uint16_t nNumberOfFrames; } XnCmosBlankingUnits; typedef struct XnI2CWriteData { uint16_t nBus; uint16_t nSlaveAddress; uint16_t cpWriteBuffer[XN_IO_MAX_I2C_BUFFER_SIZE]; uint16_t nWriteSize; } XnI2CWriteData; typedef struct XnI2CReadData { uint16_t nBus; uint16_t nSlaveAddress; uint16_t cpReadBuffer[XN_IO_MAX_I2C_BUFFER_SIZE]; uint16_t cpWriteBuffer[XN_IO_MAX_I2C_BUFFER_SIZE]; uint16_t nReadSize; uint16_t nWriteSize; } XnI2CReadData; typedef struct XnTecData { uint16_t m_SetPointVoltage; uint16_t m_CompensationVoltage; uint16_t m_TecDutyCycle; //duty cycle on heater/cooler uint16_t m_HeatMode; //TRUE - heat, FALSE - cool int32_t m_ProportionalError; int32_t m_IntegralError; int32_t m_DerivativeError; uint16_t m_ScanMode; //0 - crude, 1 - precise } XnTecData; typedef struct XnTecFastConvergenceData { int16_t m_SetPointTemperature; // set point temperature in celsius, // scaled by factor of 100 (extra precision) int16_t m_MeasuredTemperature; // measured temperature in celsius, // scaled by factor of 100 (extra precision) int32_t m_ProportionalError; // proportional error in system clocks int32_t m_IntegralError; // integral error in system clocks int32_t m_DerivativeError; // derivative error in system clocks uint16_t m_ScanMode; // 0 - initial, 1 - crude, 2 - precise uint16_t m_HeatMode; // 0 - idle, 1 - heat, 2 - cool uint16_t m_TecDutyCycle; // duty cycle on heater/cooler in percents uint16_t m_TemperatureRange; // 0 - cool, 1 - room, 2 - warm } XnTecFastConvergenceData; typedef struct XnEmitterData { uint16_t m_State; //idle, calibrating uint16_t m_SetPointVoltage; //this is what should be written to the XML uint16_t m_SetPointClocks; //target cross duty cycle uint16_t m_PD_Reading; //current cross duty cycle in system clocks(high time) uint16_t m_EmitterSet; //duty cycle on emitter set in system clocks (high time). uint16_t m_EmitterSettingLogic; //TRUE = positive logic, FALSE = negative logic uint16_t m_LightMeasureLogic; //TRUE - positive logic, FALSE - negative logic uint16_t m_IsAPCEnabled; uint16_t m_EmitterSetStepSize; // in MilliVolts uint16_t m_ApcTolerance; // in system clocks (only valid up till v5.2) uint16_t m_SubClocking; //in system clocks (only valid from v5.3) uint16_t m_Precision; // (only valid from v5.3) } XnEmitterData; typedef struct { uint16_t nId; uint16_t nAttribs; } XnFileAttributes; typedef struct { uint32_t nOffset; const char* strFileName; uint16_t nAttributes; } XnParamFileData; typedef struct { uint32_t nOffset; uint32_t nSize; unsigned char* pData; } XnParamFlashData; typedef struct { uint16_t nId; uint16_t nType; uint32_t nVersion; uint32_t nOffset; uint32_t nSize; uint16_t nCrc; uint16_t nAttributes; uint16_t nReserve; } XnFlashFile; typedef struct { XnFlashFile* pFiles; uint16_t nFiles; } XnFlashFileList; typedef struct XnProjectorFaultData { uint16_t nMinThreshold; uint16_t nMaxThreshold; int32_t bProjectorFaultEvent; } XnProjectorFaultData; typedef struct XnBist { uint32_t nTestsMask; uint32_t nFailures; } XnBist; #pragma pack (pop) #endif //_PS1080_H_libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/PSLink.h000066400000000000000000000130231264163024100300440ustar00rootroot00000000000000#ifndef __XN_PRIME_CLIENT_PROPS_H__ #define __XN_PRIME_CLIENT_PROPS_H__ #include enum { /**** Device properties ****/ /* XnDetailedVersion, get only */ LINK_PROP_FW_VERSION = 0x12000001, // "FWVersion" /* Int, get only */ LINK_PROP_VERSIONS_INFO_COUNT = 0x12000002, // "VersionsInfoCount" /* General - array - XnComponentVersion * count elements, get only */ LINK_PROP_VERSIONS_INFO = 0x12000003, // "VersionsInfo" /* Int - 0 means off, 1 means on. */ LINK_PROP_EMITTER_ACTIVE = 0x12000008, // "EmitterActive" /* String. Set only */ LINK_PROP_PRESET_FILE = 0x1200000a, // "PresetFile" /* Get only */ LINK_PROP_BOOT_STATUS = 0x1200000b, /**** Device commands ****/ /* XnCommandGetFwStreams */ LINK_COMMAND_GET_FW_STREAM_LIST = 0x1200F001, /* XnCommandCreateStream */ LINK_COMMAND_CREATE_FW_STREAM = 0x1200F002, /* XnCommandDestroyStream */ LINK_COMMAND_DESTROY_FW_STREAM = 0x1200F003, /* XnCommandStartStream */ LINK_COMMAND_START_FW_STREAM = 0x1200F004, /* XnCommandStopStream */ LINK_COMMAND_STOP_FW_STREAM = 0x1200F005, /* XnCommandGetFwStreamVideoModeList */ LINK_COMMAND_GET_FW_STREAM_VIDEO_MODE_LIST = 0x1200F006, /* XnCommandSetFwStreamVideoMode */ LINK_COMMAND_SET_FW_STREAM_VIDEO_MODE = 0x1200F007, /* XnCommandGetFwStreamVideoMode */ LINK_COMMAND_GET_FW_STREAM_VIDEO_MODE = 0x1200F008, /**** Stream properties ****/ /* Int. 1 - Shifts 9.3, 2 - Grayscale16, 3 - YUV422, 4 - Bayer8 */ LINK_PROP_PIXEL_FORMAT = 0x12001001, // "PixelFormat" /* Int. 0 - None, 1 - 8z, 2 - 16z, 3 - 24z, 4 - 6-bit, 5 - 10-bit, 6 - 11-bit, 7 - 12-bit */ LINK_PROP_COMPRESSION = 0x12001002, // "Compression" /**** Depth Stream properties ****/ /* Real, get only */ LINK_PROP_DEPTH_SCALE = 0x1200000b, // "DepthScale" /* Int, get only */ LINK_PROP_MAX_SHIFT = 0x12002001, // "MaxShift" /* Int, get only */ LINK_PROP_ZERO_PLANE_DISTANCE = 0x12002002, // "ZPD" /* Int, get only */ LINK_PROP_CONST_SHIFT = 0x12002003, // "ConstShift" /* Int, get only */ LINK_PROP_PARAM_COEFF = 0x12002004, // "ParamCoeff" /* Int, get only */ LINK_PROP_SHIFT_SCALE = 0x12002005, // "ShiftScale" /* Real, get only */ LINK_PROP_ZERO_PLANE_PIXEL_SIZE = 0x12002006, // "ZPPS" /* Real, get only */ LINK_PROP_ZERO_PLANE_OUTPUT_PIXEL_SIZE = 0x12002007, // "ZPOPS" /* Real, get only */ LINK_PROP_EMITTER_DEPTH_CMOS_DISTANCE = 0x12002008, // "LDDIS" /* General - array - MaxShift * XnDepthPixel elements, get only */ LINK_PROP_SHIFT_TO_DEPTH_TABLE = 0x12002009, // "S2D" /* General - array - MaxDepth * uint16_t elements, get only */ LINK_PROP_DEPTH_TO_SHIFT_TABLE = 0x1200200a, // "D2S" }; typedef enum XnFileZone { XN_ZONE_FACTORY = 0x0000, XN_ZONE_UPDATE = 0x0001, } XnFileZone; typedef enum XnBootErrorCode { XN_BOOT_OK = 0x0000, XN_BOOT_BAD_CRC = 0x0001, XN_BOOT_UPLOAD_IN_PROGRESS = 0x0002, XN_BOOT_FW_LOAD_FAILED = 0x0003, } XnBootErrorCode; typedef enum XnFwStreamType { XN_FW_STREAM_TYPE_COLOR = 0x0001, XN_FW_STREAM_TYPE_IR = 0x0002, XN_FW_STREAM_TYPE_SHIFTS = 0x0003, XN_FW_STREAM_TYPE_AUDIO = 0x0004, XN_FW_STREAM_TYPE_DY = 0x0005, XN_FW_STREAM_TYPE_LOG = 0x0008, } XnFwStreamType; typedef enum XnFwPixelFormat { XN_FW_PIXEL_FORMAT_NONE = 0x0000, XN_FW_PIXEL_FORMAT_SHIFTS_9_3 = 0x0001, XN_FW_PIXEL_FORMAT_GRAYSCALE16 = 0x0002, XN_FW_PIXEL_FORMAT_YUV422 = 0x0003, XN_FW_PIXEL_FORMAT_BAYER8 = 0x0004, } XnFwPixelFormat; typedef enum XnFwCompressionType { XN_FW_COMPRESSION_NONE = 0x0000, XN_FW_COMPRESSION_8Z = 0x0001, XN_FW_COMPRESSION_16Z = 0x0002, XN_FW_COMPRESSION_24Z = 0x0003, XN_FW_COMPRESSION_6_BIT_PACKED = 0x0004, XN_FW_COMPRESSION_10_BIT_PACKED = 0x0005, XN_FW_COMPRESSION_11_BIT_PACKED = 0x0006, XN_FW_COMPRESSION_12_BIT_PACKED = 0x0007, } XnFwCompressionType; #pragma pack (push, 1) #define XN_MAX_VERSION_MODIFIER_LENGTH 16 typedef struct XnDetailedVersion { uint8_t m_nMajor; uint8_t m_nMinor; uint16_t m_nMaintenance; uint32_t m_nBuild; char m_strModifier[XN_MAX_VERSION_MODIFIER_LENGTH]; } XnDetailedVersion; typedef struct XnBootStatus { XnFileZone zone; XnBootErrorCode errorCode; } XnBootStatus; typedef struct XnFwStreamInfo { XnFwStreamType type; char creationInfo[80]; } XnFwStreamInfo; typedef struct XnFwStreamVideoMode { uint32_t m_nXRes; uint32_t m_nYRes; uint32_t m_nFPS; XnFwPixelFormat m_nPixelFormat; XnFwCompressionType m_nCompression; } XnFwStreamVideoMode; typedef struct XnCommandGetFwStreamList { uint32_t count; // in: number of allocated elements in streams array. out: number of written elements in the array XnFwStreamInfo* streams; } XnCommandGetFwStreamList; typedef struct XnCommandCreateStream { XnFwStreamType type; const char* creationInfo; uint32_t id; // out } XnCommandCreateStream; typedef struct XnCommandDestroyStream { uint32_t id; } XnCommandDestroyStream; typedef struct XnCommandStartStream { uint32_t id; } XnCommandStartStream; typedef struct XnCommandStopStream { uint32_t id; } XnCommandStopStream; typedef struct XnCommandGetFwStreamVideoModeList { int streamId; uint32_t count; // in: number of allocated elements in videoModes array. out: number of written elements in the array XnFwStreamVideoMode* videoModes; } XnCommandGetFwStreamVideoModeList; typedef struct XnCommandSetFwStreamVideoMode { int streamId; XnFwStreamVideoMode videoMode; } XnCommandSetFwStreamVideoMode; typedef struct XnCommandGetFwStreamVideoMode { int streamId; XnFwStreamVideoMode videoMode; // out } XnCommandGetFwStreamVideoMode; #pragma pack (pop) #endif //__XN_PRIME_CLIENT_PROPS_H__ libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/PrimeSense.h000066400000000000000000000161101264163024100307560ustar00rootroot00000000000000/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _PRIME_SENSE_H_ #define _PRIME_SENSE_H_ #include /** * Additional properties for PrimeSense devices * * @remarks * properties structure is 0x1D27XXYY where XX is range and YY is code. * range values: * 00 - common stream properties * 10 - depth stream properties * E0 - device commands * F0 - device properties */ enum { // Stream Properties PS_PROPERTY_DUMP_DATA = 0x1d270001, // boolean // Device Properties PS_PROPERTY_USB_INTERFACE = 0x1d27F001, // values from XnUsbInterfaceType }; /** * Additional commands for PrimeSense devices * * @remarks * Commands structure is 0x1D27XXYY where XX is range and YY is code. * range values: * E0 - device commands */ enum { // Device Commands - use via invoke() PS_COMMAND_AHB_READ = 0x1d27E001, // XnCommandAHB PS_COMMAND_AHB_WRITE = 0x1d27E002, // XnCommandAHB PS_COMMAND_I2C_READ = 0x1d27E003, // XnCommandI2C PS_COMMAND_I2C_WRITE = 0x1d27E004, // XnCommandI2C PS_COMMAND_SOFT_RESET = 0x1d27E005, // no arguments PS_COMMAND_POWER_RESET = 0x1d27E006, // no arguments PS_COMMAND_BEGIN_FIRMWARE_UPDATE = 0x1d27E007, // no arguments PS_COMMAND_END_FIRMWARE_UPDATE = 0x1d27E008, // no arguments PS_COMMAND_UPLOAD_FILE = 0x1d27E009, // XnCommandUploadFile PS_COMMAND_DOWNLOAD_FILE = 0x1d27E00A, // XnCommandDownloadFile PS_COMMAND_GET_FILE_LIST = 0x1d27E00B, // an array of XnFileEntry PS_COMMAND_FORMAT_ZONE = 0x1d27E00C, // XnCommandFormatZone PS_COMMAND_DUMP_ENDPOINT = 0x1d27E00D, // XnCommandDumpEndpoint PS_COMMAND_GET_I2C_DEVICE_LIST = 0x1d27E00E, // XnCommandGetI2CDevices PS_COMMAND_GET_BIST_LIST = 0x1d27E00F, // XnCommandGetBistList PS_COMMAND_EXECUTE_BIST = 0x1d27E010, // XnCommandExecuteBist PS_COMMAND_USB_TEST = 0x1d27E011, // XnCommandUsbTest PS_COMMAND_GET_LOG_MASK_LIST = 0x1d27E012, // XnCommandGetLogMaskList PS_COMMAND_SET_LOG_MASK_STATE = 0x1d27E013, // XnCommandSetLogMaskState PS_COMMAND_START_LOG = 0x1d27E014, // no arguments PS_COMMAND_STOP_LOG = 0x1d27E015, // no arguments }; typedef enum XnUsbInterfaceType { PS_USB_INTERFACE_DONT_CARE = 0, PS_USB_INTERFACE_ISO_ENDPOINTS = 1, PS_USB_INTERFACE_BULK_ENDPOINTS = 2, } XnUsbInterfaceType; #pragma pack (push, 1) // Data Types typedef struct XnFwFileVersion { uint8_t major; uint8_t minor; uint8_t maintenance; uint8_t build; } XnFwFileVersion; typedef enum XnFwFileFlags { XN_FILE_FLAG_BAD_CRC = 0x0001, } XnFwFileFlags; typedef struct XnFwFileEntry { char name[32]; XnFwFileVersion version; uint32_t address; uint32_t size; uint16_t crc; uint16_t zone; XnFwFileFlags flags; // bitmap } XnFwFileEntry; typedef struct XnI2CDeviceInfo { uint32_t id; char name[32]; } XnI2CDeviceInfo; typedef struct XnBistInfo { uint32_t id; char name[32]; } XnBistInfo; typedef struct XnFwLogMask { uint32_t id; char name[32]; } XnFwLogMask; typedef struct XnUsbTestEndpointResult { double averageBytesPerSecond; uint32_t lostPackets; } XnUsbTestEndpointResult; // Commands typedef struct XnCommandAHB { uint32_t address; // Address of this register uint32_t offsetInBits; // Offset of the field in bits within address uint32_t widthInBits; // Width of the field in bits uint32_t value; // For read requests, this is where the actual value will be filled. For write requests, the value to write. } XnCommandAHB; typedef struct XnCommandI2C { uint32_t deviceID; // Device to communicate with uint32_t addressSize; // Size of the address, in bytes (1-4) uint32_t address; // Address uint32_t valueSize; // Size of the value, in bytes (1-4) uint32_t mask; // For write request - a mask to be applied to the value. For read requests - ignored. uint32_t value; // For write request - the value to be written. For read requests - the place where the actual value is written to } XnCommandI2C; typedef struct XnCommandUploadFile { const char* filePath; uint32_t uploadToFactory; } XnCommandUploadFile; typedef struct XnCommandDownloadFile { uint16_t zone; const char* firmwareFileName; const char* targetPath; } XnCommandDownloadFile; typedef struct XnCommandGetFileList { uint32_t count; // in: number of allocated elements in files array. out: number of written elements in the array XnFwFileEntry* files; } XnCommandGetFileList; typedef struct XnCommandFormatZone { uint8_t zone; } XnCommandFormatZone; typedef struct XnCommandDumpEndpoint { uint8_t endpoint; bool enabled; } XnCommandDumpEndpoint; typedef struct XnCommandGetI2CDeviceList { uint32_t count; // in: number of allocated elements in devices array. out: number of written elements in the array XnI2CDeviceInfo* devices; } XnCommandGetI2CDeviceList; typedef struct XnCommandGetBistList { uint32_t count; // in: number of allocated elements in tests array. out: number of written elements in the array XnBistInfo* tests; } XnCommandGetBistList; typedef struct XnCommandExecuteBist { uint32_t id; uint32_t errorCode; uint32_t extraDataSize; // in: number of allocated bytes in extraData. out: number of written bytes in extraData uint8_t* extraData; } XnCommandExecuteBist; typedef struct XnCommandUsbTest { uint32_t seconds; uint32_t endpointCount; // in: number of allocated bytes in endpoints array. out: number of written bytes in array XnUsbTestEndpointResult* endpoints; } XnCommandUsbTest; typedef struct XnCommandGetLogMaskList { uint32_t count; // in: number of allocated elements in masks array. out: number of written elements in the array XnFwLogMask* masks; } XnCommandGetLogMaskList; typedef struct XnCommandSetLogMaskState { uint32_t mask; bool enabled; } XnCommandSetLogMaskState; #pragma pack (pop) #endif //_PRIME_SENSE_H_libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Win32/000077500000000000000000000000001264163024100274365ustar00rootroot00000000000000OniPlatformWin32.h000066400000000000000000000131161264163024100326070ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/extern/OpenNI-Linux-x64-2.2.0.33/Include/Win32/***************************************************************************** * * * OpenNI 2.x Alpha * * Copyright (C) 2012 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * 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. * * * *****************************************************************************/ #ifndef _ONI_PLATFORM_WIN32_H_ #define _ONI_PLATFORM_WIN32_H_ //--------------------------------------------------------------------------- // Prerequisites //--------------------------------------------------------------------------- #ifndef WINVER // Allow use of features specific to Windows XP or later #define WINVER 0x0501 #endif #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later #define _WIN32_WINNT 0x0501 #endif #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later #define _WIN32_WINDOWS 0x0410 #endif #ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later #define _WIN32_IE 0x0600 #endif #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Undeprecate CRT functions #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE 1 #endif //--------------------------------------------------------------------------- // Includes //--------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #if _MSC_VER < 1600 // Visual Studio 2008 and older doesn't have stdint.h... typedef signed char int8_t; typedef short int16_t; typedef int int32_t; typedef __int64 int64_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; #else #include #endif //--------------------------------------------------------------------------- // Platform Basic Definition //--------------------------------------------------------------------------- #define ONI_PLATFORM ONI_PLATFORM_WIN32 #define ONI_PLATFORM_STRING "Win32" //--------------------------------------------------------------------------- // Platform Capabilities //--------------------------------------------------------------------------- #define ONI_PLATFORM_ENDIAN_TYPE ONI_PLATFORM_IS_LITTLE_ENDIAN #define ONI_PLATFORM_SUPPORTS_DYNAMIC_LIBS 1 //--------------------------------------------------------------------------- // Memory //--------------------------------------------------------------------------- /** The default memory alignment. */ #define ONI_DEFAULT_MEM_ALIGN 16 /** The thread static declarator (using TLS). */ #define ONI_THREAD_STATIC __declspec(thread) //--------------------------------------------------------------------------- // Files //--------------------------------------------------------------------------- /** The maximum allowed file path size (in bytes). */ #define ONI_FILE_MAX_PATH MAX_PATH //--------------------------------------------------------------------------- // Call backs //--------------------------------------------------------------------------- /** The std call type. */ #define ONI_STDCALL __stdcall /** The call back calling convention. */ #define ONI_CALLBACK_TYPE ONI_STDCALL /** The C and C++ calling convension. */ #define ONI_C_DECL __cdecl //--------------------------------------------------------------------------- // Macros //--------------------------------------------------------------------------- /** Returns the date and time at compile time. */ #define ONI_TIMESTAMP __DATE__ " " __TIME__ /** Converts n into a pre-processor string. */ #define ONI_STRINGIFY(n) ONI_STRINGIFY_HELPER(n) #define ONI_STRINGIFY_HELPER(n) #n //--------------------------------------------------------------------------- // API Export/Import Macros //--------------------------------------------------------------------------- /** Indicates an exported shared library function. */ #define ONI_API_EXPORT __declspec(dllexport) /** Indicates an imported shared library function. */ #define ONI_API_IMPORT __declspec(dllimport) /** Indicates a deprecated function */ #if _MSC_VER < 1400 // Before VS2005 there was no support for declspec deprecated... #define ONI_API_DEPRECATED(msg) #else #define ONI_API_DEPRECATED(msg) __declspec(deprecated(msg)) #endif #endif //_ONI_PLATFORM_WIN32_H_ libfreenect-0.5.3/OpenNI2-FreenectDriver/src/000077500000000000000000000000001264163024100207065ustar00rootroot00000000000000libfreenect-0.5.3/OpenNI2-FreenectDriver/src/ColorStream.cpp000066400000000000000000000052761264163024100236560ustar00rootroot00000000000000#include #include "ColorStream.hpp" using namespace FreenectDriver; ColorStream::ColorStream(Freenect::FreenectDevice* pDevice) : VideoStream(pDevice) { video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 640, 480, 30); setVideoMode(video_mode); pDevice->startVideo(); } // Add video modes here as you implement them ColorStream::FreenectVideoModeMap ColorStream::getSupportedVideoModes() { FreenectVideoModeMap modes; // pixelFormat, resolutionX, resolutionY, fps freenect_video_format, freenect_resolution modes[makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 640, 480, 30)] = std::pair(FREENECT_VIDEO_RGB, FREENECT_RESOLUTION_MEDIUM); return modes; /* working format possiblities FREENECT_VIDEO_RGB FREENECT_VIDEO_YUV_RGB FREENECT_VIDEO_YUV_RAW */ } OniStatus ColorStream::setVideoMode(OniVideoMode requested_mode) { FreenectVideoModeMap supported_video_modes = getSupportedVideoModes(); FreenectVideoModeMap::const_iterator matched_mode_iter = supported_video_modes.find(requested_mode); if (matched_mode_iter == supported_video_modes.end()) return ONI_STATUS_NOT_SUPPORTED; freenect_video_format format = matched_mode_iter->second.first; freenect_resolution resolution = matched_mode_iter->second.second; try { device->setVideoFormat(format, resolution); } catch (std::runtime_error e) { LogError("Format " + to_string(format) + " and resolution " + to_string(resolution) + " combination not supported by libfreenect"); return ONI_STATUS_NOT_SUPPORTED; } video_mode = requested_mode; return ONI_STATUS_OK; } void ColorStream::populateFrame(void* data, OniFrame* frame) const { frame->sensorType = sensor_type; frame->stride = video_mode.resolutionX * 3; frame->cropOriginX = 0; frame->cropOriginY = 0; frame->croppingEnabled = false; // copy stream buffer from freenect switch (video_mode.pixelFormat) { default: LogError("Pixel format " + to_string(video_mode.pixelFormat) + " not supported by populateFrame()"); return; case ONI_PIXEL_FORMAT_RGB888: uint8_t* source = static_cast(data); uint8_t* target = static_cast(frame->data); std::copy(source, source + frame->dataSize, target); return; } } /* color video modes reference FREENECT_VIDEO_RGB = 0, //< Decompressed RGB mode (demosaicing done by libfreenect) FREENECT_VIDEO_BAYER = 1, //< Bayer compressed mode (raw information from camera) FREENECT_VIDEO_YUV_RGB = 5, //< YUV RGB mode FREENECT_VIDEO_YUV_RAW = 6, //< YUV Raw mode ONI_PIXEL_FORMAT_RGB888 = 200, ONI_PIXEL_FORMAT_YUV422 = 201, ONI_PIXEL_FORMAT_JPEG = 204, */ libfreenect-0.5.3/OpenNI2-FreenectDriver/src/ColorStream.hpp000066400000000000000000000121221264163024100236470ustar00rootroot00000000000000#pragma once #include // for transform() #include // for M_PI #include "libfreenect.hpp" #include "Driver/OniDriverAPI.h" #include "VideoStream.hpp" namespace FreenectDriver { class ColorStream : public VideoStream { public: // from NUI library & converted to radians static const float DIAGONAL_FOV = 73.9 * (M_PI / 180); static const float HORIZONTAL_FOV = 62 * (M_PI / 180); static const float VERTICAL_FOV = 48.6 * (M_PI / 180); private: typedef std::map< OniVideoMode, std::pair > FreenectVideoModeMap; static const OniSensorType sensor_type = ONI_SENSOR_COLOR; static FreenectVideoModeMap getSupportedVideoModes(); OniStatus setVideoMode(OniVideoMode requested_mode); void populateFrame(void* data, OniFrame* frame) const; bool auto_white_balance; bool auto_exposure; public: ColorStream(Freenect::FreenectDevice* pDevice); //~ColorStream() { } static OniSensorInfo getSensorInfo() { FreenectVideoModeMap supported_modes = getSupportedVideoModes(); OniVideoMode* modes = new OniVideoMode[supported_modes.size()]; std::transform(supported_modes.begin(), supported_modes.end(), modes, ExtractKey()); OniSensorInfo sensors = { sensor_type, static_cast(supported_modes.size()), modes }; return sensors; } // from StreamBase OniBool isPropertySupported(int propertyId) { switch(propertyId) { default: return VideoStream::isPropertySupported(propertyId); case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: case ONI_STREAM_PROPERTY_VERTICAL_FOV: case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: return true; } } OniStatus getProperty(int propertyId, void* data, int* pDataSize) { switch (propertyId) { default: return VideoStream::getProperty(propertyId, data, pDataSize); case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float (radians) { if (*pDataSize != sizeof(float)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_HORIZONTAL_FOV"); return ONI_STATUS_ERROR; } *(static_cast(data)) = HORIZONTAL_FOV; return ONI_STATUS_OK; } case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float (radians) { if (*pDataSize != sizeof(float)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_VERTICAL_FOV"); return ONI_STATUS_ERROR; } *(static_cast(data)) = VERTICAL_FOV; return ONI_STATUS_OK; } // camera case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool { if (*pDataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = auto_white_balance; return ONI_STATUS_OK; } case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool { if (*pDataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_EXPOSURE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = auto_exposure; return ONI_STATUS_OK; } } } OniStatus setProperty(int propertyId, const void* data, int dataSize) { switch (propertyId) { default: return VideoStream::setProperty(propertyId, data, dataSize); // camera case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool { if (dataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE"); return ONI_STATUS_ERROR; } auto_white_balance = *(static_cast(data)); int ret = device->setFlag(FREENECT_AUTO_WHITE_BALANCE, auto_white_balance); return (ret == 0) ? ONI_STATUS_OK : ONI_STATUS_ERROR; } case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool { if (dataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_EXPOSURE"); return ONI_STATUS_ERROR; } auto_exposure = *(static_cast(data)); int ret = device->setFlag(FREENECT_AUTO_WHITE_BALANCE, auto_exposure); return (ret == 0) ? ONI_STATUS_OK : ONI_STATUS_ERROR; } case ONI_STREAM_PROPERTY_MIRRORING: // OniBool { if (dataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_MIRRORING"); return ONI_STATUS_ERROR; } mirroring = *(static_cast(data)); int ret = device->setFlag(FREENECT_MIRROR_VIDEO, mirroring); return (ret == 0) ? ONI_STATUS_OK : ONI_STATUS_ERROR; } } } }; } libfreenect-0.5.3/OpenNI2-FreenectDriver/src/D2S.h000066400000000000000000001561541264163024100214630ustar00rootroot00000000000000const unsigned short D2S[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 10, 13, 17, 20, 23, 27, 30, 33, 36, 40, 43, 46, 49, 52, 55, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 88, 91, 94, 97, 100, 103, 106, 108, 111, 114, 117, 119, 122, 125, 128, 130, 133, 136, 138, 141, 143, 146, 149, 151, 154, 156, 159, 161, 164, 166, 169, 171, 174, 176, 178, 181, 183, 186, 188, 190, 193, 195, 197, 200, 202, 204, 206, 209, 211, 213, 215, 218, 220, 222, 224, 226, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 252, 254, 256, 258, 260, 262, 264, 266, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 288, 290, 292, 294, 296, 298, 299, 301, 303, 305, 307, 308, 310, 312, 314, 315, 317, 319, 321, 322, 324, 326, 327, 329, 331, 332, 334, 336, 337, 339, 341, 342, 344, 345, 347, 349, 350, 352, 353, 355, 357, 358, 360, 361, 363, 364, 366, 367, 369, 370, 372, 373, 375, 376, 378, 379, 381, 382, 383, 385, 386, 388, 389, 391, 392, 393, 395, 396, 398, 399, 400, 402, 403, 404, 406, 407, 409, 410, 411, 413, 414, 415, 416, 418, 419, 420, 422, 423, 424, 426, 427, 428, 429, 431, 432, 433, 434, 436, 437, 438, 439, 441, 442, 443, 444, 445, 447, 448, 449, 450, 451, 452, 454, 455, 456, 457, 458, 459, 461, 462, 463, 464, 465, 466, 467, 468, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 532, 533, 534, 535, 536, 537, 538, 539, 540, 540, 541, 542, 543, 544, 545, 546, 546, 547, 548, 549, 550, 551, 551, 552, 553, 554, 555, 556, 556, 557, 558, 559, 560, 561, 561, 562, 563, 564, 565, 565, 566, 567, 568, 568, 569, 570, 571, 572, 572, 573, 574, 575, 575, 576, 577, 578, 578, 579, 580, 581, 581, 582, 583, 584, 584, 585, 586, 587, 587, 588, 589, 590, 590, 591, 592, 592, 593, 594, 594, 595, 596, 597, 597, 598, 599, 599, 600, 601, 601, 602, 603, 604, 604, 605, 606, 606, 607, 608, 608, 609, 610, 610, 611, 612, 612, 613, 614, 614, 615, 615, 616, 617, 617, 618, 619, 619, 620, 621, 621, 622, 622, 623, 624, 624, 625, 626, 626, 627, 627, 628, 629, 629, 630, 631, 631, 632, 632, 633, 634, 634, 635, 635, 636, 636, 637, 638, 638, 639, 639, 640, 641, 641, 642, 642, 643, 643, 644, 645, 645, 646, 646, 647, 647, 648, 649, 649, 650, 650, 651, 651, 652, 652, 653, 654, 654, 655, 655, 656, 656, 657, 657, 658, 658, 659, 659, 660, 661, 661, 662, 662, 663, 663, 664, 664, 665, 665, 666, 666, 667, 667, 668, 668, 669, 669, 670, 670, 671, 671, 672, 672, 673, 673, 674, 674, 675, 675, 676, 676, 677, 677, 678, 678, 679, 679, 680, 680, 681, 681, 682, 682, 683, 683, 684, 684, 685, 685, 685, 686, 686, 687, 687, 688, 688, 689, 689, 690, 690, 691, 691, 691, 692, 692, 693, 693, 694, 694, 695, 695, 696, 696, 696, 697, 697, 698, 698, 699, 699, 699, 700, 700, 701, 701, 702, 702, 703, 703, 703, 704, 704, 705, 705, 706, 706, 706, 707, 707, 708, 708, 708, 709, 709, 710, 710, 711, 711, 711, 712, 712, 713, 713, 713, 714, 714, 715, 715, 715, 716, 716, 717, 717, 717, 718, 718, 719, 719, 719, 720, 720, 721, 721, 721, 722, 722, 723, 723, 723, 724, 724, 724, 725, 725, 726, 726, 726, 727, 727, 727, 728, 728, 729, 729, 729, 730, 730, 730, 731, 731, 732, 732, 732, 733, 733, 733, 734, 734, 734, 735, 735, 736, 736, 736, 737, 737, 737, 738, 738, 738, 739, 739, 739, 740, 740, 741, 741, 741, 742, 742, 742, 743, 743, 743, 744, 744, 744, 745, 745, 745, 746, 746, 746, 747, 747, 747, 748, 748, 748, 749, 749, 749, 750, 750, 750, 751, 751, 751, 752, 752, 752, 753, 753, 753, 754, 754, 754, 755, 755, 755, 756, 756, 756, 756, 757, 757, 757, 758, 758, 758, 759, 759, 759, 760, 760, 760, 761, 761, 761, 761, 762, 762, 762, 763, 763, 763, 764, 764, 764, 765, 765, 765, 765, 766, 766, 766, 767, 767, 767, 768, 768, 768, 768, 769, 769, 769, 770, 770, 770, 770, 771, 771, 771, 772, 772, 772, 773, 773, 773, 773, 774, 774, 774, 775, 775, 775, 775, 776, 776, 776, 776, 777, 777, 777, 778, 778, 778, 778, 779, 779, 779, 780, 780, 780, 780, 781, 781, 781, 781, 782, 782, 782, 783, 783, 783, 783, 784, 784, 784, 784, 785, 785, 785, 785, 786, 786, 786, 787, 787, 787, 787, 788, 788, 788, 788, 789, 789, 789, 789, 790, 790, 790, 790, 791, 791, 791, 791, 792, 792, 792, 792, 793, 793, 793, 793, 794, 794, 794, 794, 795, 795, 795, 795, 796, 796, 796, 796, 797, 797, 797, 797, 798, 798, 798, 798, 799, 799, 799, 799, 800, 800, 800, 800, 801, 801, 801, 801, 801, 802, 802, 802, 802, 803, 803, 803, 803, 804, 804, 804, 804, 805, 805, 805, 805, 805, 806, 806, 806, 806, 807, 807, 807, 807, 808, 808, 808, 808, 808, 809, 809, 809, 809, 810, 810, 810, 810, 810, 811, 811, 811, 811, 812, 812, 812, 812, 812, 813, 813, 813, 813, 813, 814, 814, 814, 814, 815, 815, 815, 815, 815, 816, 816, 816, 816, 817, 817, 817, 817, 817, 818, 818, 818, 818, 818, 819, 819, 819, 819, 819, 820, 820, 820, 820, 820, 821, 821, 821, 821, 822, 822, 822, 822, 822, 823, 823, 823, 823, 823, 824, 824, 824, 824, 824, 825, 825, 825, 825, 825, 826, 826, 826, 826, 826, 827, 827, 827, 827, 827, 828, 828, 828, 828, 828, 828, 829, 829, 829, 829, 829, 830, 830, 830, 830, 830, 831, 831, 831, 831, 831, 832, 832, 832, 832, 832, 832, 833, 833, 833, 833, 833, 834, 834, 834, 834, 834, 835, 835, 835, 835, 835, 835, 836, 836, 836, 836, 836, 837, 837, 837, 837, 837, 837, 838, 838, 838, 838, 838, 839, 839, 839, 839, 839, 839, 840, 840, 840, 840, 840, 841, 841, 841, 841, 841, 841, 842, 842, 842, 842, 842, 842, 843, 843, 843, 843, 843, 843, 844, 844, 844, 844, 844, 845, 845, 845, 845, 845, 845, 846, 846, 846, 846, 846, 846, 847, 847, 847, 847, 847, 847, 848, 848, 848, 848, 848, 848, 849, 849, 849, 849, 849, 849, 850, 850, 850, 850, 850, 850, 850, 851, 851, 851, 851, 851, 851, 852, 852, 852, 852, 852, 852, 853, 853, 853, 853, 853, 853, 854, 854, 854, 854, 854, 854, 854, 855, 855, 855, 855, 855, 855, 856, 856, 856, 856, 856, 856, 857, 857, 857, 857, 857, 857, 857, 858, 858, 858, 858, 858, 858, 858, 859, 859, 859, 859, 859, 859, 860, 860, 860, 860, 860, 860, 860, 861, 861, 861, 861, 861, 861, 861, 862, 862, 862, 862, 862, 862, 863, 863, 863, 863, 863, 863, 863, 864, 864, 864, 864, 864, 864, 864, 865, 865, 865, 865, 865, 865, 865, 866, 866, 866, 866, 866, 866, 866, 867, 867, 867, 867, 867, 867, 867, 868, 868, 868, 868, 868, 868, 868, 868, 869, 869, 869, 869, 869, 869, 869, 870, 870, 870, 870, 870, 870, 870, 871, 871, 871, 871, 871, 871, 871, 871, 872, 872, 872, 872, 872, 872, 872, 873, 873, 873, 873, 873, 873, 873, 873, 874, 874, 874, 874, 874, 874, 874, 875, 875, 875, 875, 875, 875, 875, 875, 876, 876, 876, 876, 876, 876, 876, 876, 877, 877, 877, 877, 877, 877, 877, 878, 878, 878, 878, 878, 878, 878, 878, 879, 879, 879, 879, 879, 879, 879, 879, 880, 880, 880, 880, 880, 880, 880, 880, 881, 881, 881, 881, 881, 881, 881, 881, 882, 882, 882, 882, 882, 882, 882, 882, 882, 883, 883, 883, 883, 883, 883, 883, 883, 884, 884, 884, 884, 884, 884, 884, 884, 885, 885, 885, 885, 885, 885, 885, 885, 885, 886, 886, 886, 886, 886, 886, 886, 886, 887, 887, 887, 887, 887, 887, 887, 887, 887, 888, 888, 888, 888, 888, 888, 888, 888, 888, 889, 889, 889, 889, 889, 889, 889, 889, 890, 890, 890, 890, 890, 890, 890, 890, 890, 891, 891, 891, 891, 891, 891, 891, 891, 891, 892, 892, 892, 892, 892, 892, 892, 892, 892, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 894, 894, 894, 894, 894, 894, 894, 894, 894, 895, 895, 895, 895, 895, 895, 895, 895, 895, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 897, 897, 897, 897, 897, 897, 897, 897, 897, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052}; libfreenect-0.5.3/OpenNI2-FreenectDriver/src/DepthStream.cpp000066400000000000000000000113071264163024100236340ustar00rootroot00000000000000#include #include "DepthStream.hpp" using namespace FreenectDriver; DepthStream::DepthStream(Freenect::FreenectDevice* pDevice) : VideoStream(pDevice) { video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, 640, 480, 30); image_registration_mode = ONI_IMAGE_REGISTRATION_OFF; setVideoMode(video_mode); pDevice->startDepth(); } // Add video modes here as you implement them // Note: if image_registration_mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR, // setVideoFormat() will try FREENECT_DEPTH_REGISTERED first then fall back on what is set here. DepthStream::FreenectDepthModeMap DepthStream::getSupportedVideoModes() { FreenectDepthModeMap modes; // pixelFormat, resolutionX, resolutionY, fps modes[makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, 640, 480, 30)] = std::pair(FREENECT_DEPTH_MM, FREENECT_RESOLUTION_MEDIUM); return modes; } OniStatus DepthStream::setVideoMode(OniVideoMode requested_mode) { FreenectDepthModeMap supported_video_modes = getSupportedVideoModes(); FreenectDepthModeMap::const_iterator matched_mode_iter = supported_video_modes.find(requested_mode); if (matched_mode_iter == supported_video_modes.end()) return ONI_STATUS_NOT_SUPPORTED; freenect_depth_format format = matched_mode_iter->second.first; freenect_resolution resolution = matched_mode_iter->second.second; if (image_registration_mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR) // try forcing registration mode format = FREENECT_DEPTH_REGISTERED; try { device->setDepthFormat(format, resolution); } catch (std::runtime_error e) { LogError("Format " + to_string(format) + " and resolution " + to_string(resolution) + " combination not supported by libfreenect"); if (image_registration_mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR) { LogError("Could not enable image registration format; falling back to format defined in getSupportedVideoModes()"); image_registration_mode = ONI_IMAGE_REGISTRATION_OFF; return setVideoMode(requested_mode); } return ONI_STATUS_NOT_SUPPORTED; } video_mode = requested_mode; return ONI_STATUS_OK; } void DepthStream::populateFrame(void* data, OniFrame* frame) const { frame->sensorType = sensor_type; frame->stride = video_mode.resolutionX * sizeof(uint16_t); if (cropping.enabled) { frame->height = cropping.height; frame->width = cropping.width; frame->cropOriginX = cropping.originX; frame->cropOriginY = cropping.originY; frame->croppingEnabled = true; } else { frame->cropOriginX = 0; frame->cropOriginY = 0; frame->croppingEnabled = false; } // copy stream buffer from freenect uint16_t* source = static_cast(data) + frame->cropOriginX + frame->cropOriginY * video_mode.resolutionX; uint16_t* target = static_cast(frame->data); const unsigned int skipWidth = video_mode.resolutionX - frame->width; if (mirroring) { target += frame->width; for (int y = 0; y < frame->height; y++) { for (int x = 0; x < frame->width; x++) { *target-- = *source++; } source += skipWidth; target += 2 * frame->width; } } else { for (int y = 0; y < frame->height; y++) { for (int x = 0; x < frame->width; x++) { *target++ = *source++; } source += skipWidth; } } /* uint16_t* data_ptr = static_cast(data); uint16_t* frame_data = static_cast(frame->data); if (mirroring) { for (unsigned int i = 0; i < frame->dataSize / 2; i++) { // find corresponding mirrored pixel unsigned int row = i / video_mode.resolutionX; unsigned int col = video_mode.resolutionX - (i % video_mode.resolutionX); unsigned int target = (row * video_mode.resolutionX) + col; // copy it to this pixel frame_data[i] = data_ptr[target]; } } else std::copy(data_ptr, data_ptr+frame->dataSize / 2, frame_data); */ } /* depth video modes reference FREENECT_DEPTH_11BIT = 0, //< 11 bit depth information in one uint16_t/pixel FREENECT_DEPTH_10BIT = 1, //< 10 bit depth information in one uint16_t/pixel FREENECT_DEPTH_11BIT_PACKED = 2, //< 11 bit packed depth information FREENECT_DEPTH_10BIT_PACKED = 3, //< 10 bit packed depth information FREENECT_DEPTH_REGISTERED = 4, //< processed depth data in mm, aligned to 640x480 RGB FREENECT_DEPTH_MM = 5, //< depth to each pixel in mm, but left unaligned to RGB image FREENECT_DEPTH_DUMMY = 2147483647, //< Dummy value to force enum to be 32 bits wide ONI_PIXEL_FORMAT_DEPTH_1_MM = 100, ONI_PIXEL_FORMAT_DEPTH_100_UM = 101, ONI_PIXEL_FORMAT_SHIFT_9_2 = 102, ONI_PIXEL_FORMAT_SHIFT_9_3 = 103, */ libfreenect-0.5.3/OpenNI2-FreenectDriver/src/DepthStream.hpp000066400000000000000000000246521264163024100236500ustar00rootroot00000000000000#pragma once #include // for transform() #include // for M_PI #include // for memcpy #include "libfreenect.hpp" #include "Driver/OniDriverAPI.h" #include "PS1080.h" #include "VideoStream.hpp" #include "S2D.h" #include "D2S.h" namespace FreenectDriver { class DepthStream : public VideoStream { public: // from NUI library and converted to radians static const float DIAGONAL_FOV = 70 * (M_PI / 180); static const float HORIZONTAL_FOV = 58.5 * (M_PI / 180); static const float VERTICAL_FOV = 45.6 * (M_PI / 180); // from DepthKinectStream.cpp static const int MAX_VALUE = 10000; static const unsigned long long GAIN_VAL = 42; static const unsigned long long CONST_SHIFT_VAL = 200; static const unsigned long long MAX_SHIFT_VAL = 2047; static const unsigned long long PARAM_COEFF_VAL = 4; static const unsigned long long SHIFT_SCALE_VAL = 10; static const unsigned long long ZERO_PLANE_DISTANCE_VAL = 120; static const double ZERO_PLANE_PIXEL_SIZE_VAL = 0.10520000010728836; static const double EMITTER_DCMOS_DISTANCE_VAL = 7.5; private: typedef std::map< OniVideoMode, std::pair > FreenectDepthModeMap; static const OniSensorType sensor_type = ONI_SENSOR_DEPTH; OniImageRegistrationMode image_registration_mode; static FreenectDepthModeMap getSupportedVideoModes(); OniStatus setVideoMode(OniVideoMode requested_mode); void populateFrame(void* data, OniFrame* frame) const; public: DepthStream(Freenect::FreenectDevice* pDevice); //~DepthStream() { } static OniSensorInfo getSensorInfo() { FreenectDepthModeMap supported_modes = getSupportedVideoModes(); OniVideoMode* modes = new OniVideoMode[supported_modes.size()]; std::transform(supported_modes.begin(), supported_modes.end(), modes, ExtractKey()); OniSensorInfo sensors = { sensor_type, static_cast(supported_modes.size()), modes }; return sensors; } OniImageRegistrationMode getImageRegistrationMode() const { return image_registration_mode; } OniStatus setImageRegistrationMode(OniImageRegistrationMode mode) { if (!isImageRegistrationModeSupported(mode)) return ONI_STATUS_NOT_SUPPORTED; image_registration_mode = mode; return setVideoMode(video_mode); } // from StreamBase OniBool isImageRegistrationModeSupported(OniImageRegistrationMode mode) { return (mode == ONI_IMAGE_REGISTRATION_OFF || mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR); } OniBool isPropertySupported(int propertyId) { switch(propertyId) { default: return VideoStream::isPropertySupported(propertyId); case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: case ONI_STREAM_PROPERTY_VERTICAL_FOV: case ONI_STREAM_PROPERTY_MAX_VALUE: case XN_STREAM_PROPERTY_GAIN: case XN_STREAM_PROPERTY_CONST_SHIFT: case XN_STREAM_PROPERTY_MAX_SHIFT: case XN_STREAM_PROPERTY_PARAM_COEFF: case XN_STREAM_PROPERTY_SHIFT_SCALE: case XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE: case XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE: case XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE: case XN_STREAM_PROPERTY_S2D_TABLE: case XN_STREAM_PROPERTY_D2S_TABLE: return true; } } OniStatus getProperty(int propertyId, void* data, int* pDataSize) { switch (propertyId) { default: return VideoStream::getProperty(propertyId, data, pDataSize); case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float (radians) if (*pDataSize != sizeof(float)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_HORIZONTAL_FOV"); return ONI_STATUS_ERROR; } *(static_cast(data)) = HORIZONTAL_FOV; return ONI_STATUS_OK; case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float (radians) if (*pDataSize != sizeof(float)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_VERTICAL_FOV"); return ONI_STATUS_ERROR; } *(static_cast(data)) = VERTICAL_FOV; return ONI_STATUS_OK; case ONI_STREAM_PROPERTY_MAX_VALUE: // int if (*pDataSize != sizeof(int)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_MAX_VALUE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = MAX_VALUE; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_PIXEL_REGISTRATION: // XnPixelRegistration (get only) case XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED: // unsigned long long case XN_STREAM_PROPERTY_HOLE_FILTER: // unsigned long long case XN_STREAM_PROPERTY_REGISTRATION_TYPE: // XnProcessingType case XN_STREAM_PROPERTY_AGC_BIN: // XnDepthAGCBin* case XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR: // unsigned long long case XN_STREAM_PROPERTY_DCMOS_RCMOS_DISTANCE: // double case XN_STREAM_PROPERTY_CLOSE_RANGE: // unsigned long long return ONI_STATUS_NOT_SUPPORTED; case XN_STREAM_PROPERTY_GAIN: // unsigned long long if (*pDataSize != sizeof(unsigned long long)) { LogError("Unexpected size for XN_STREAM_PROPERTY_GAIN"); return ONI_STATUS_ERROR; } *(static_cast(data)) = GAIN_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_CONST_SHIFT: // unsigned long long if (*pDataSize != sizeof(unsigned long long)) { LogError("Unexpected size for XN_STREAM_PROPERTY_CONST_SHIFT"); return ONI_STATUS_ERROR; } *(static_cast(data)) = CONST_SHIFT_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_MAX_SHIFT: // unsigned long long if (*pDataSize != sizeof(unsigned long long)) { LogError("Unexpected size for XN_STREAM_PROPERTY_MAX_SHIFT"); return ONI_STATUS_ERROR; } *(static_cast(data)) = MAX_SHIFT_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_PARAM_COEFF: // unsigned long long if (*pDataSize != sizeof(unsigned long long)) { LogError("Unexpected size for XN_STREAM_PROPERTY_PARAM_COEFF"); return ONI_STATUS_ERROR; } *(static_cast(data)) = PARAM_COEFF_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_SHIFT_SCALE: // unsigned long long if (*pDataSize != sizeof(unsigned long long)) { LogError("Unexpected size for XN_STREAM_PROPERTY_SHIFT_SCALE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = SHIFT_SCALE_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE: // unsigned long long if (*pDataSize != sizeof(unsigned long long)) { LogError("Unexpected size for XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = ZERO_PLANE_DISTANCE_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE: // double if (*pDataSize != sizeof(double)) { LogError("Unexpected size for XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = ZERO_PLANE_PIXEL_SIZE_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE: // double if (*pDataSize != sizeof(double)) { LogError("Unexpected size for XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = EMITTER_DCMOS_DISTANCE_VAL; return ONI_STATUS_OK; case XN_STREAM_PROPERTY_S2D_TABLE: // OniDepthPixel[] *pDataSize = sizeof(S2D); //std::copy(S2D, S2D+1, static_cast(data)); memcpy(data, S2D, *pDataSize); return ONI_STATUS_OK; case XN_STREAM_PROPERTY_D2S_TABLE: // unsigned short[] *pDataSize = sizeof(D2S); //std::copy(D2S, D2S+1, static_cast(data)); memcpy(data, D2S, *pDataSize); return ONI_STATUS_OK; } } void notifyAllProperties() { double nDouble; int size = sizeof(nDouble); getProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, &nDouble, &size); raisePropertyChanged(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, &nDouble, size); unsigned long long nUll; size = sizeof(nUll); getProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &nUll, size); getProperty(XN_STREAM_PROPERTY_GAIN, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_GAIN, &nUll, size); getProperty(XN_STREAM_PROPERTY_CONST_SHIFT, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_CONST_SHIFT, &nUll, size); getProperty(XN_STREAM_PROPERTY_MAX_SHIFT, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_MAX_SHIFT, &nUll, size); getProperty(XN_STREAM_PROPERTY_SHIFT_SCALE, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_SHIFT_SCALE, &nUll, size); getProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &nUll, size); getProperty(XN_STREAM_PROPERTY_PARAM_COEFF, &nUll, &size); raisePropertyChanged(XN_STREAM_PROPERTY_PARAM_COEFF, &nUll, size); int nInt; size = sizeof(nInt); getProperty(ONI_STREAM_PROPERTY_MAX_VALUE, &nInt, &size); raisePropertyChanged(ONI_STREAM_PROPERTY_MAX_VALUE, &nInt, size); unsigned short nBuff[10001]; size = sizeof(S2D); getProperty(XN_STREAM_PROPERTY_S2D_TABLE, nBuff, &size); raisePropertyChanged(XN_STREAM_PROPERTY_S2D_TABLE, nBuff, size); size = sizeof(D2S); getProperty(XN_STREAM_PROPERTY_D2S_TABLE, nBuff, &size); raisePropertyChanged(XN_STREAM_PROPERTY_D2S_TABLE, nBuff, size); VideoStream::notifyAllProperties(); } }; } libfreenect-0.5.3/OpenNI2-FreenectDriver/src/DeviceDriver.cpp000066400000000000000000000261401264163024100237700ustar00rootroot00000000000000/** * FreenectDriver * Copyright 2013 Benn Snyder * * 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. */ #include #include #include "Driver/OniDriverAPI.h" #include "freenect_internal.h" #include "libfreenect.hpp" #include "DepthStream.hpp" #include "ColorStream.hpp" namespace FreenectDriver { class Device : public oni::driver::DeviceBase, public Freenect::FreenectDevice { private: ColorStream* color; DepthStream* depth; // for Freenect::FreenectDevice void DepthCallback(void* data, uint32_t timestamp) { depth->buildFrame(data, timestamp); } void VideoCallback(void* data, uint32_t timestamp) { color->buildFrame(data, timestamp); } public: Device(freenect_context* fn_ctx, int index) : Freenect::FreenectDevice(fn_ctx, index), color(NULL), depth(NULL) { } ~Device() { destroyStream(color); destroyStream(depth); } // for DeviceBase OniBool isImageRegistrationModeSupported(OniImageRegistrationMode mode) { return depth->isImageRegistrationModeSupported(mode); } OniStatus getSensorInfoList(OniSensorInfo** pSensors, int* numSensors) { *numSensors = 2; OniSensorInfo * sensors = new OniSensorInfo[*numSensors]; sensors[0] = depth->getSensorInfo(); sensors[1] = color->getSensorInfo(); *pSensors = sensors; return ONI_STATUS_OK; } oni::driver::StreamBase* createStream(OniSensorType sensorType) { switch (sensorType) { default: LogError("Cannot create a stream of type " + to_string(sensorType)); return NULL; case ONI_SENSOR_COLOR: if (! color) color = new ColorStream(this); return color; case ONI_SENSOR_DEPTH: if (! depth) depth = new DepthStream(this); return depth; // todo: IR } } void destroyStream(oni::driver::StreamBase* pStream) { if (pStream == NULL) return; if (pStream == color) { Freenect::FreenectDevice::stopVideo(); delete color; color = NULL; } if (pStream == depth) { Freenect::FreenectDevice::stopDepth(); delete depth; depth = NULL; } } // todo: fill out properties OniBool isPropertySupported(int propertyId) { if (propertyId == ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION) return true; return false; } OniStatus getProperty(int propertyId, void* data, int* pDataSize) { switch (propertyId) { default: case ONI_DEVICE_PROPERTY_FIRMWARE_VERSION: // string case ONI_DEVICE_PROPERTY_DRIVER_VERSION: // OniVersion case ONI_DEVICE_PROPERTY_HARDWARE_VERSION: // int case ONI_DEVICE_PROPERTY_SERIAL_NUMBER: // string case ONI_DEVICE_PROPERTY_ERROR_STATE: // ? // files case ONI_DEVICE_PROPERTY_PLAYBACK_SPEED: // float case ONI_DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED: // OniBool // xn case XN_MODULE_PROPERTY_USB_INTERFACE: // XnSensorUsbInterface case XN_MODULE_PROPERTY_MIRROR: // bool case XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP: // unsigned long long case XN_MODULE_PROPERTY_LEAN_INIT: // unsigned long long case XN_MODULE_PROPERTY_SERIAL_NUMBER: // unsigned long long case XN_MODULE_PROPERTY_VERSION: // XnVersions return ONI_STATUS_NOT_SUPPORTED; case ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION: // OniImageRegistrationMode if (*pDataSize != sizeof(OniImageRegistrationMode)) { LogError("Unexpected size for ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION"); return ONI_STATUS_ERROR; } *(static_cast(data)) = depth->getImageRegistrationMode(); return ONI_STATUS_OK; } } OniStatus setProperty(int propertyId, const void* data, int dataSize) { switch (propertyId) { default: case ONI_DEVICE_PROPERTY_FIRMWARE_VERSION: // By implementation case ONI_DEVICE_PROPERTY_DRIVER_VERSION: // OniVersion case ONI_DEVICE_PROPERTY_HARDWARE_VERSION: // int case ONI_DEVICE_PROPERTY_SERIAL_NUMBER: // string case ONI_DEVICE_PROPERTY_ERROR_STATE: // ? // files case ONI_DEVICE_PROPERTY_PLAYBACK_SPEED: // float case ONI_DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED: // OniBool // xn case XN_MODULE_PROPERTY_USB_INTERFACE: // XnSensorUsbInterface case XN_MODULE_PROPERTY_MIRROR: // bool case XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP: // unsigned long long case XN_MODULE_PROPERTY_LEAN_INIT: // unsigned long long case XN_MODULE_PROPERTY_SERIAL_NUMBER: // unsigned long long case XN_MODULE_PROPERTY_VERSION: // XnVersions // xn commands case XN_MODULE_PROPERTY_FIRMWARE_PARAM: // XnInnerParam case XN_MODULE_PROPERTY_RESET: // unsigned long long case XN_MODULE_PROPERTY_IMAGE_CONTROL: // XnControlProcessingData case XN_MODULE_PROPERTY_DEPTH_CONTROL: // XnControlProcessingData case XN_MODULE_PROPERTY_AHB: // XnAHBData case XN_MODULE_PROPERTY_LED_STATE: // XnLedState return ONI_STATUS_NOT_SUPPORTED; case ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION: // OniImageRegistrationMode if (dataSize != sizeof(OniImageRegistrationMode)) { LogError("Unexpected size for ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION"); return ONI_STATUS_ERROR; } return depth->setImageRegistrationMode(*(static_cast(data))); } } OniBool isCommandSupported(int commandId) { switch (commandId) { default: case ONI_DEVICE_COMMAND_SEEK: return false; } } OniStatus invoke(int commandId, void* data, int dataSize) { switch (commandId) { default: case ONI_DEVICE_COMMAND_SEEK: // OniSeek return ONI_STATUS_NOT_SUPPORTED; } } /* todo: for DeviceBase virtual OniStatus tryManualTrigger() {return ONI_STATUS_OK;} */ }; class Driver : public oni::driver::DriverBase, private Freenect::Freenect { private: typedef std::map OniDeviceMap; OniDeviceMap devices; static std::string devid_to_uri(int id) { return "freenect://" + to_string(id); } static int uri_to_devid(const std::string uri) { int id; std::istringstream is(uri); is.seekg(strlen("freenect://")); is >> id; return id; } public: Driver(OniDriverServices* pDriverServices) : DriverBase(pDriverServices) { WriteMessage("Using libfreenect v" + to_string(PROJECT_VER)); freenect_set_log_level(m_ctx, FREENECT_LOG_DEBUG); freenect_select_subdevices(m_ctx, FREENECT_DEVICE_CAMERA); // OpenNI2 doesn't use MOTOR or AUDIO DriverServices = &getServices(); } ~Driver() { shutdown(); } // for DriverBase OniStatus initialize(oni::driver::DeviceConnectedCallback connectedCallback, oni::driver::DeviceDisconnectedCallback disconnectedCallback, oni::driver::DeviceStateChangedCallback deviceStateChangedCallback, void* pCookie) { DriverBase::initialize(connectedCallback, disconnectedCallback, deviceStateChangedCallback, pCookie); for (int i = 0; i < Freenect::deviceCount(); i++) { std::string uri = devid_to_uri(i); WriteMessage("Found device " + uri); OniDeviceInfo info; strncpy(info.uri, uri.c_str(), ONI_MAX_STR); strncpy(info.vendor, "Microsoft", ONI_MAX_STR); strncpy(info.name, "Kinect", ONI_MAX_STR); devices[info] = NULL; deviceConnected(&info); deviceStateChanged(&info, 0); freenect_device* dev; if (freenect_open_device(m_ctx, &dev, i) == 0) { info.usbVendorId = dev->usb_cam.VID; info.usbProductId = dev->usb_cam.PID; freenect_close_device(dev); } else { WriteMessage("Unable to open device to query VID/PID"); } } return ONI_STATUS_OK; } oni::driver::DeviceBase* deviceOpen(const char* uri, const char* mode = NULL) { for (OniDeviceMap::iterator iter = devices.begin(); iter != devices.end(); iter++) { if (strcmp(iter->first.uri, uri) == 0) // found { if (iter->second) // already open { return iter->second; } else { WriteMessage("Opening device " + std::string(uri)); int id = uri_to_devid(iter->first.uri); Device* device = &createDevice(id); iter->second = device; return device; } } } LogError("Could not find device " + std::string(uri)); return NULL; } void deviceClose(oni::driver::DeviceBase* pDevice) { for (OniDeviceMap::iterator iter = devices.begin(); iter != devices.end(); iter++) { if (iter->second == pDevice) { WriteMessage("Closing device " + std::string(iter->first.uri)); int id = uri_to_devid(iter->first.uri); devices.erase(iter); deleteDevice(id); return; } } LogError("Could not close unrecognized device"); } OniStatus tryDevice(const char* uri) { oni::driver::DeviceBase* device = deviceOpen(uri); if (! device) return ONI_STATUS_ERROR; deviceClose(device); return ONI_STATUS_OK; } void shutdown() { for (OniDeviceMap::iterator iter = devices.begin(); iter != devices.end(); iter++) { WriteMessage("Closing device " + std::string(iter->first.uri)); int id = uri_to_devid(iter->first.uri); deleteDevice(id); } devices.clear(); } /* todo: for DriverBase virtual void* enableFrameSync(oni::driver::StreamBase** pStreams, int streamCount); virtual void disableFrameSync(void* frameSyncGroup); */ }; } // macros defined in XnLib (not included) - workaround #define XN_NEW(type, arg...) new type(arg) #define XN_DELETE(p) delete(p) ONI_EXPORT_DRIVER(FreenectDriver::Driver); #undef XN_NEW #undef XN_DELETE libfreenect-0.5.3/OpenNI2-FreenectDriver/src/S2D.h000066400000000000000000000211231264163024100214460ustar00rootroot00000000000000const uint16_t S2D[] = { 0, 315, 315, 315, 316, 316, 316, 316, 317, 317, 317, 318, 318, 318, 319, 319, 319, 319, 320, 320, 320, 321, 321, 321, 322, 322, 322, 322, 323, 323, 323, 324, 324, 324, 325, 325, 325, 326, 326, 326, 326, 327, 327, 327, 328, 328, 328, 329, 329, 329, 330, 330, 330, 331, 331, 331, 332, 332, 332, 332, 333, 333, 333, 334, 334, 334, 335, 335, 335, 336, 336, 336, 337, 337, 337, 338, 338, 338, 339, 339, 339, 340, 340, 340, 341, 341, 341, 342, 342, 343, 343, 343, 344, 344, 344, 345, 345, 345, 346, 346, 346, 347, 347, 347, 348, 348, 348, 349, 349, 350, 350, 350, 351, 351, 351, 352, 352, 352, 353, 353, 354, 354, 354, 355, 355, 355, 356, 356, 356, 357, 357, 358, 358, 358, 359, 359, 359, 360, 360, 361, 361, 361, 362, 362, 363, 363, 363, 364, 364, 364, 365, 365, 366, 366, 366, 367, 367, 368, 368, 368, 369, 369, 370, 370, 370, 371, 371, 372, 372, 372, 373, 373, 374, 374, 374, 375, 375, 376, 376, 377, 377, 377, 378, 378, 379, 379, 379, 380, 380, 381, 381, 382, 382, 382, 383, 383, 384, 384, 385, 385, 385, 386, 386, 387, 387, 388, 388, 389, 389, 389, 390, 390, 391, 391, 392, 392, 393, 393, 393, 394, 394, 395, 395, 396, 396, 397, 397, 398, 398, 398, 399, 399, 400, 400, 401, 401, 402, 402, 403, 403, 404, 404, 405, 405, 406, 406, 407, 407, 408, 408, 409, 409, 409, 410, 410, 411, 411, 412, 412, 413, 413, 414, 414, 415, 415, 416, 416, 417, 418, 418, 419, 419, 420, 420, 421, 421, 422, 422, 423, 423, 424, 424, 425, 425, 426, 426, 427, 427, 428, 429, 429, 430, 430, 431, 431, 432, 432, 433, 433, 434, 435, 435, 436, 436, 437, 437, 438, 438, 439, 440, 440, 441, 441, 442, 442, 443, 444, 444, 445, 445, 446, 446, 447, 448, 448, 449, 449, 450, 451, 451, 452, 452, 453, 454, 454, 455, 455, 456, 457, 457, 458, 458, 459, 460, 460, 461, 462, 462, 463, 463, 464, 465, 465, 466, 467, 467, 468, 468, 469, 470, 470, 471, 472, 472, 473, 474, 474, 475, 476, 476, 477, 478, 478, 479, 480, 480, 481, 482, 482, 483, 484, 484, 485, 486, 487, 487, 488, 489, 489, 490, 491, 491, 492, 493, 494, 494, 495, 496, 496, 497, 498, 499, 499, 500, 501, 502, 502, 503, 504, 504, 505, 506, 507, 507, 508, 509, 510, 511, 511, 512, 513, 514, 514, 515, 516, 517, 517, 518, 519, 520, 521, 521, 522, 523, 524, 525, 525, 526, 527, 528, 529, 529, 530, 531, 532, 533, 534, 534, 535, 536, 537, 538, 539, 540, 540, 541, 542, 543, 544, 545, 546, 546, 547, 548, 549, 550, 551, 552, 553, 554, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 618, 619, 620, 621, 622, 623, 624, 625, 627, 628, 629, 630, 631, 632, 634, 635, 636, 637, 638, 640, 641, 642, 643, 644, 646, 647, 648, 649, 650, 652, 653, 654, 655, 657, 658, 659, 661, 662, 663, 664, 666, 667, 668, 670, 671, 672, 674, 675, 676, 678, 679, 680, 682, 683, 684, 686, 687, 688, 690, 691, 693, 694, 696, 697, 698, 700, 701, 703, 704, 706, 707, 708, 710, 711, 713, 714, 716, 717, 719, 720, 722, 723, 725, 727, 728, 730, 731, 733, 734, 736, 738, 739, 741, 742, 744, 746, 747, 749, 750, 752, 754, 755, 757, 759, 761, 762, 764, 766, 767, 769, 771, 773, 774, 776, 778, 780, 781, 783, 785, 787, 789, 790, 792, 794, 796, 798, 800, 802, 803, 805, 807, 809, 811, 813, 815, 817, 819, 821, 823, 825, 827, 829, 831, 833, 835, 837, 839, 841, 843, 845, 847, 849, 851, 854, 856, 858, 860, 862, 864, 867, 869, 871, 873, 875, 878, 880, 882, 885, 887, 889, 891, 894, 896, 898, 901, 903, 906, 908, 910, 913, 915, 918, 920, 923, 925, 928, 930, 933, 935, 938, 940, 943, 946, 948, 951, 954, 956, 959, 962, 964, 967, 970, 973, 975, 978, 981, 984, 987, 989, 992, 995, 998, 1001, 1004, 1007, 1010, 1013, 1016, 1019, 1022, 1025, 1028, 1031, 1034, 1038, 1041, 1044, 1047, 1050, 1054, 1057, 1060, 1063, 1067, 1070, 1073, 1077, 1080, 1084, 1087, 1090, 1094, 1097, 1101, 1105, 1108, 1112, 1115, 1119, 1123, 1126, 1130, 1134, 1138, 1141, 1145, 1149, 1153, 1157, 1161, 1165, 1169, 1173, 1177, 1181, 1185, 1189, 1193, 1197, 1202, 1206, 1210, 1214, 1219, 1223, 1227, 1232, 1236, 1241, 1245, 1250, 1255, 1259, 1264, 1268, 1273, 1278, 1283, 1288, 1292, 1297, 1302, 1307, 1312, 1317, 1322, 1328, 1333, 1338, 1343, 1349, 1354, 1359, 1365, 1370, 1376, 1381, 1387, 1392, 1398, 1404, 1410, 1415, 1421, 1427, 1433, 1439, 1445, 1452, 1458, 1464, 1470, 1477, 1483, 1489, 1496, 1503, 1509, 1516, 1523, 1529, 1536, 1543, 1550, 1557, 1564, 1572, 1579, 1586, 1594, 1601, 1609, 1616, 1624, 1632, 1639, 1647, 1655, 1663, 1671, 1680, 1688, 1696, 1705, 1713, 1722, 1731, 1739, 1748, 1757, 1766, 1776, 1785, 1794, 1804, 1813, 1823, 1833, 1843, 1853, 1863, 1873, 1883, 1894, 1904, 1915, 1926, 1936, 1947, 1959, 1970, 1981, 1993, 2005, 2016, 2028, 2040, 2053, 2065, 2078, 2090, 2103, 2116, 2129, 2143, 2156, 2170, 2184, 2198, 2212, 2226, 2241, 2256, 2271, 2286, 2301, 2317, 2333, 2349, 2365, 2381, 2398, 2415, 2432, 2450, 2467, 2485, 2503, 2522, 2541, 2560, 2579, 2598, 2618, 2639, 2659, 2680, 2701, 2723, 2744, 2767, 2789, 2812, 2835, 2859, 2883, 2908, 2933, 2958, 2984, 3010, 3037, 3064, 3092, 3120, 3149, 3178, 3208, 3238, 3269, 3300, 3333, 3365, 3399, 3433, 3468, 3503, 3539, 3576, 3614, 3653, 3692, 3732, 3774, 3816, 3859, 3903, 3948, 3994, 4041, 4089, 4139, 4190, 4241, 4295, 4349, 4405, 4463, 4522, 4582, 4645, 4708, 4774, 4842, 4911, 4983, 5056, 5132, 5210, 5291, 5374, 5460, 5548, 5640, 5734, 5832, 5933, 6038, 6146, 6259, 6375, 6497, 6622, 6753, 6889, 7030, 7178, 7332, 7492, 7660, 7835, 8019, 8212, 8413, 8626, 8849, 9084, 9331, 9593, 9870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; libfreenect-0.5.3/OpenNI2-FreenectDriver/src/Utility.hpp000066400000000000000000000037041264163024100230660ustar00rootroot00000000000000// This file contains symbols that may be used by any class or don't really go anywhere else. #pragma once #include #include "Driver/OniDriverAPI.h" // Oni helpers static OniVideoMode makeOniVideoMode(OniPixelFormat pixel_format, int resolution_x, int resolution_y, int frames_per_second) { OniVideoMode mode; mode.pixelFormat = pixel_format; mode.resolutionX = resolution_x; mode.resolutionY = resolution_y; mode.fps = frames_per_second; return mode; } static bool operator==(const OniVideoMode& left, const OniVideoMode& right) { return (left.pixelFormat == right.pixelFormat && left.resolutionX == right.resolutionX && left.resolutionY == right.resolutionY && left.fps == right.fps); } static bool operator<(const OniVideoMode& left, const OniVideoMode& right) { return (left.resolutionX * left.resolutionY < right.resolutionX * right.resolutionY); } static bool operator<(const OniDeviceInfo& left, const OniDeviceInfo& right) { return (strcmp(left.uri, right.uri) < 0); } /// Extracts `first` from `pair`, for transforming a map into its keys. struct ExtractKey { template typename T::first_type operator()(T pair) const { return pair.first; } }; // holding out on C++11 template static std::string to_string(const T& n) { std::ostringstream oss; oss << n; return oss.str(); } // global logging namespace FreenectDriver { static void WriteMessage(std::string info) { std::cout << "OpenNI2-FreenectDriver: " << info << std::endl; } // DriverServices is set in DeviceDriver.cpp so all files can call errorLoggerAppend() static oni::driver::DriverServices* DriverServices; static void LogError(std::string error) { // errorLoggerAppend() doesn't seem to go anywhere, so WriteMessage also WriteMessage("(ERROR) " + error); if (DriverServices != NULL) DriverServices->errorLoggerAppend(std::string("OpenNI2-FreenectDriver: " + error).c_str()); } } libfreenect-0.5.3/OpenNI2-FreenectDriver/src/VideoStream.hpp000066400000000000000000000156001264163024100236430ustar00rootroot00000000000000#pragma once #include "libfreenect.hpp" #include "PS1080.h" #include "Utility.hpp" namespace FreenectDriver { class VideoStream : public oni::driver::StreamBase { private: unsigned int frame_id; // number each frame virtual OniStatus setVideoMode(OniVideoMode requested_mode) = 0; virtual void populateFrame(void* data, OniFrame* frame) const = 0; protected: static const OniSensorType sensor_type; Freenect::FreenectDevice* device; bool running; // buildFrame() does something iff true OniVideoMode video_mode; OniCropping cropping; bool mirroring; public: VideoStream(Freenect::FreenectDevice* device) : frame_id(1), device(device), mirroring(false) { // joy of structs memset(&cropping, 0, sizeof(cropping)); memset(&video_mode, 0, sizeof(video_mode)); } //~VideoStream() { stop(); } void buildFrame(void* data, uint32_t timestamp) { if (!running) return; OniFrame* frame = getServices().acquireFrame(); frame->frameIndex = frame_id++; frame->timestamp = timestamp; frame->videoMode = video_mode; frame->width = video_mode.resolutionX; frame->height = video_mode.resolutionY; populateFrame(data, frame); raiseNewFrame(frame); getServices().releaseFrame(frame); } // from StreamBase OniStatus start() { running = true; return ONI_STATUS_OK; } void stop() { running = false; } // only add to property handlers if the property is generic to all children // otherwise, implement in child and call these in default case OniBool isPropertySupported(int propertyId) { switch(propertyId) { case ONI_STREAM_PROPERTY_VIDEO_MODE: case ONI_STREAM_PROPERTY_CROPPING: case ONI_STREAM_PROPERTY_MIRRORING: return true; default: return false; } } virtual OniStatus getProperty(int propertyId, void* data, int* pDataSize) { switch (propertyId) { default: case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float: radians case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float: radians case ONI_STREAM_PROPERTY_MAX_VALUE: // int case ONI_STREAM_PROPERTY_MIN_VALUE: // int case ONI_STREAM_PROPERTY_STRIDE: // int case ONI_STREAM_PROPERTY_NUMBER_OF_FRAMES: // int // camera case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool // xn case XN_STREAM_PROPERTY_INPUT_FORMAT: // unsigned long long case XN_STREAM_PROPERTY_CROPPING_MODE: // XnCroppingMode return ONI_STATUS_NOT_SUPPORTED; case ONI_STREAM_PROPERTY_VIDEO_MODE: // OniVideoMode* if (*pDataSize != sizeof(OniVideoMode)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_VIDEO_MODE"); return ONI_STATUS_ERROR; } *(static_cast(data)) = video_mode; return ONI_STATUS_OK; case ONI_STREAM_PROPERTY_CROPPING: // OniCropping* if (*pDataSize != sizeof(OniCropping)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_CROPPING"); return ONI_STATUS_ERROR; } *(static_cast(data)) = cropping; return ONI_STATUS_OK; case ONI_STREAM_PROPERTY_MIRRORING: // OniBool if (*pDataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_MIRRORING"); return ONI_STATUS_ERROR; } *(static_cast(data)) = mirroring; return ONI_STATUS_OK; } } virtual OniStatus setProperty(int propertyId, const void* data, int dataSize) { switch (propertyId) { default: case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float: radians case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float: radians case ONI_STREAM_PROPERTY_MAX_VALUE: // int case ONI_STREAM_PROPERTY_MIN_VALUE: // int case ONI_STREAM_PROPERTY_STRIDE: // int case ONI_STREAM_PROPERTY_NUMBER_OF_FRAMES: // int // camera case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool // xn case XN_STREAM_PROPERTY_INPUT_FORMAT: // unsigned long long case XN_STREAM_PROPERTY_CROPPING_MODE: // XnCroppingMode return ONI_STATUS_NOT_SUPPORTED; case ONI_STREAM_PROPERTY_VIDEO_MODE: // OniVideoMode* if (dataSize != sizeof(OniVideoMode)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_VIDEO_MODE"); return ONI_STATUS_ERROR; } if (ONI_STATUS_OK != setVideoMode(*(static_cast(data)))) return ONI_STATUS_NOT_SUPPORTED; raisePropertyChanged(propertyId, data, dataSize); return ONI_STATUS_OK; case ONI_STREAM_PROPERTY_CROPPING: // OniCropping* if (dataSize != sizeof(OniCropping)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_CROPPING"); return ONI_STATUS_ERROR; } cropping = *(static_cast(data)); raisePropertyChanged(propertyId, data, dataSize); return ONI_STATUS_OK; case ONI_STREAM_PROPERTY_MIRRORING: // OniBool if (dataSize != sizeof(OniBool)) { LogError("Unexpected size for ONI_STREAM_PROPERTY_MIRRORING"); return ONI_STATUS_ERROR; } mirroring = *(static_cast(data)); raisePropertyChanged(propertyId, data, dataSize); return ONI_STATUS_OK; } } /* todo : from StreamBase virtual OniStatus convertDepthToColorCoordinates(StreamBase* colorStream, int depthX, int depthY, OniDepthPixel depthZ, int* pColorX, int* pColorY) { return ONI_STATUS_NOT_SUPPORTED; } */ }; } /* image video modes reference FREENECT_VIDEO_RGB = 0, //< Decompressed RGB mode (demosaicing done by libfreenect) FREENECT_VIDEO_BAYER = 1, //< Bayer compressed mode (raw information from camera) FREENECT_VIDEO_IR_8BIT = 2, //< 8-bit IR mode FREENECT_VIDEO_IR_10BIT = 3, //< 10-bit IR mode FREENECT_VIDEO_IR_10BIT_PACKED = 4, //< 10-bit packed IR mode FREENECT_VIDEO_YUV_RGB = 5, //< YUV RGB mode FREENECT_VIDEO_YUV_RAW = 6, //< YUV Raw mode FREENECT_VIDEO_DUMMY = 2147483647, //< Dummy value to force enum to be 32 bits wide ONI_PIXEL_FORMAT_RGB888 = 200, ONI_PIXEL_FORMAT_YUV422 = 201, ONI_PIXEL_FORMAT_GRAY8 = 202, ONI_PIXEL_FORMAT_GRAY16 = 203, ONI_PIXEL_FORMAT_JPEG = 204, */ libfreenect-0.5.3/README.md000066400000000000000000000146601264163024100152660ustar00rootroot00000000000000libfreenect =========== libfreenect is a userspace driver for the Microsoft Kinect. It runs on Linux, OSX, and Windows and supports - RGB and Depth Images - Motors - Accelerometer - LED - Audio # Build Instructions To build libfreenect, you'll need - [libusb](http://libusb.info) >= 1.0.18 - [CMake](http://cmake.org) >= 2.6 - [python](http://python.org) == 2.* (only if BUILD_PYTHON=ON or BUILD_REDIST_PACKAGE=OFF) For the examples, you'll need - OpenGL (included with OSX) - glut (included with OSX) - [pthreads-win32](http://sourceforge.net/projects/pthreads4w/) (Windows) For audio support, you must have firmware to upload to the Kinect. If you specify a non-redistributable package, firmware will be downloaded automatically: cmake -L .. -DBUILD_REDIST_PACKAGE=OFF Note that the downloaded firmware may not be legal to redistribute! ## Fetch & Build git clone https://github.com/OpenKinect/libfreenect cd libfreenect mkdir build cd build cmake -L .. make # if you don't have `make` or don't want color output # cmake --build . You can specify a build with debug symbols: cmake -L .. -DCMAKE_BUILD_TYPE=debug # or with optimizations # cmake -L .. -DCMAKE_BUILD_TYPE=RelWithDebInfo You can build .deb, .rpm, and/or .tgz packages with `cpack`: cmake .. -L -DBUILD_CPACK_DEB=ON -DBUILD_CPACK_RPM=ON -DBUILD_CPACK_TGZ=ON cpack ## OSX If you don't have a package manager, install [Homebrew](http://brew.sh/). For a manual build, see [the wiki](http://openkinect.org/wiki/Getting_Started#Manual_Build_under_OSX). ### Homebrew brew install libfreenect # or get the very latest: # brew install --HEAD libfreenect ### MacPorts sudo port install git-core cmake libusb libtool Continue with [Fetch & Build](#fetch-build). ## Linux Remember to install the [udev rules](https://github.com/OpenKinect/libfreenect/tree/master/platform/linux/udev). For a manual build, see [the wiki](http://openkinect.org/wiki/Getting_Started#Manual_Build_on_Linux). ### Ubuntu/Debian/Mint The version packaged in Ubuntu may be very old. To install newer packaged builds, see [the wiki](http://openkinect.org/wiki/Getting_Started#Ubuntu.2FDebian). Continue with this section for a manual build. sudo apt-get install git cmake build-essential libusb-1.0-0-dev # only if you are building the examples: sudo apt-get install freeglut3-dev libxmu-dev libxi-dev Continue with [Fetch & Build](#fetch-build). There is also a [debian branch](https://github.com/OpenKinect/libfreenect/tree/debian) for packaging purposes. ### Gentoo Linux There is a live ebuild for your convenience in [platform/linux/portage/dev-libs/libfreenect/](https://github.com/OpenKinect/libfreenect/tree/master/platform/linux/portage/dev-libs/libfreenect). ### Arch Linux There is a [libfreenect](https://aur.archlinux.org/packages/libfreenect) PKGBUILD in the AUR. Alternately, the [libfreenect-git](https://aur.archlinux.org/packages/libfreenect-git) PKGBUILD builds the very latest. ## Windows As of February 2015, libusb still [does not support](https://github.com/libusb/libusb/issues/46) isochronous transfers on Windows. This support may be patched in by performing these steps or their GUI equivalent. git clone https://github.com/libusb/libusb.git cd libusb git remote add jblake https://github.com/JoshBlake/libusbx.git git fetch jblake git cherry-pick c5b0af4 1c74211 MSBuild.exe msvc/libusb_2013.sln Use [Zadig](http://zadig.akeo.ie/) to install the libusbK driver for each device you wish to use. Follow [Fetch & Build](#fetch-build) or use Github and CMake GUI tools. Remember to supply paths to CMake so it can find dependencies. For example: cmake .. -DLIBUSB_1_INCLUDE_DIR="C:\path\to\patched\libusb\include" -DLIBUSB_1_LIBRARY="C:\path\to\patched\libusb\libusb.lib" # Wrappers Interfaces to various languages are provided in [wrappers/](https://github.com/OpenKinect/libfreenect/tree/master/wrappers). Wrappers are not guaranteed to be API stable or up to date. - C (using a synchronous API) - C++ - C# - python - ruby - actionscript - Java (JNA) ## Python cd wrappers/python # if you have cython and want to rebuild the binding # cython freenect.pyx python2 setup.py build_ext --inplace For example, start with [demo_cv_async.py](https://github.com/OpenKinect/libfreenect/tree/master/wrappers/python/demo_cv_async.py). # Code Contributions In order of importance: - Make sure to sign commits: `git commit -s` - Use a [feature branch](https://www.atlassian.com/git/workflows#!workflow-feature-branch) in your own fork and target master with pull requests - Tab indentation, no trailing whitespace # Maintainers Ongoing Development and Maintenance by the OpenKinect Community http://www.openkinect.org - Original Code and Engineering: Hector Martin (marcan) - Community Lead: Josh Blake (JoshB) - Integration: Kyle Machulis (qDot) # License The libfreenect project is covered under a dual Apache v2/GPL v2 license. The licensing criteria are listed below, as well as at the top of each source file in the repo. ``` This file is part of the OpenKinect Project. http://www.openkinect.org Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file for details. This code is licensed to you under the terms of the Apache License, version 2.0, or, at your option, the terms of the GNU General Public License, version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, or the following URLs: http://www.apache.org/licenses/LICENSE-2.0 http://www.gnu.org/licenses/gpl-2.0.txt If you redistribute this file in source form, modified or unmodified, you may: - Leave this header intact and distribute it under the same terms, accompanying it with the APACHE20 and GPL2 files, or - Delete the Apache 2.0 clause and accompany it with the GPL2 file, or - Delete the GPL v2 clause and accompany it with the APACHE20 file In all cases you must keep the copyright notice intact and include a copy of the CONTRIB file. Binary distributions must follow the binary distribution requirements of either License. ``` # More Information Information about the OpenKinect project can be found at http://www.openkinect.org For questions, support, and discussion, check out the google groups mailing list at http://groups.google.com/group/openkinect Or the IRC channel at \#openkinect on [Freenode](http://freenode.net/) We are also on twitter at http://twitter.com/openkinect libfreenect-0.5.3/cmake_modules/000077500000000000000000000000001264163024100166105ustar00rootroot00000000000000libfreenect-0.5.3/cmake_modules/FindOS.cmake000066400000000000000000000037331264163024100207420ustar00rootroot00000000000000# Check the OS type. # CMake does not distinguish Linux from other Unices. STRING (REGEX MATCH "Linux" PROJECT_OS_LINUX ${CMAKE_SYSTEM_NAME}) # Nor *BSD STRING (REGEX MATCH "BSD" PROJECT_OS_BSD ${CMAKE_SYSTEM_NAME}) # Or Solaris. I'm seeing a trend, here STRING (REGEX MATCH "SunOS" PROJECT_OS_SOLARIS ${CMAKE_SYSTEM_NAME}) # Windows is easy (for once) IF (WIN32) SET (PROJECT_OS_WIN TRUE BOOL INTERNAL) ENDIF (WIN32) # Check if it's an Apple OS IF (APPLE) # Check if it's OS X or another MacOS (that's got to be pretty unlikely) STRING (REGEX MATCH "Darwin" PROJECT_OS_OSX ${CMAKE_SYSTEM_NAME}) IF (NOT PROJECT_OS_OSX) SET (PROJECT_OS_MACOS TRUE BOOL INTERNAL) ENDIF (NOT PROJECT_OS_OSX) ENDIF (APPLE) # QNX IF (QNXNTO) SET (PROJECT_OS_QNX TRUE BOOL INTERNAL) ENDIF (QNXNTO) IF (PROJECT_OS_LINUX) MESSAGE (STATUS "Operating system is Linux") ELSEIF (PROJECT_OS_BSD) MESSAGE (STATUS "Operating system is BSD") ELSEIF (PROJECT_OS_WIN) MESSAGE (STATUS "Operating system is Windows") ELSEIF (PROJECT_OS_OSX) MESSAGE (STATUS "Operating system is Apple MacOS X") ELSEIF (PROJECT_OS_MACOS) MESSAGE (STATUS "Operating system is Apple MacOS (not OS X)") ELSEIF (PROJECT_OS_QNX) MESSAGE (STATUS "Operating system is QNX") ELSEIF (PROJECT_OS_SOLARIS) MESSAGE (STATUS "Operating system is Solaris") ELSE (PROJECT_OS_LINUX) MESSAGE (STATUS "Operating system is generic Unix") ENDIF (PROJECT_OS_LINUX) MESSAGE (STATUS "Got System Processor ${CMAKE_SYSTEM_PROCESSOR}") # 32 or 64 bit Linux IF (PROJECT_OS_LINUX) # Set the library directory suffix accordingly IF (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") SET (PROJECT_PROC_64BIT TRUE BOOL INTERNAL) MESSAGE (STATUS "Linux x86_64 Detected") ELSEIF (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64") MESSAGE (STATUS "Linux ppc64 Detected") SET (PROJECT_PROC_64BIT TRUE BOOL INTERNAL) ENDIF (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") ENDIF (PROJECT_OS_LINUX) libfreenect-0.5.3/cmake_modules/FindThreads.cmake000066400000000000000000000207251264163024100220130ustar00rootroot00000000000000# Updated FindThreads.cmake that supports pthread-win32 # Downloaded from http://www.vtk.org/Bug/bug_view_advanced_page.php?bug_id=6399 # - This module determines the thread library of the system. # # The following variables are set # CMAKE_THREAD_LIBS_INIT - the thread library # CMAKE_USE_SPROC_INIT - are we using sproc? # CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads? # CMAKE_USE_PTHREADS_INIT - are we using pthreads # CMAKE_HP_PTHREADS_INIT - are we using hp pthreads # # If use of pthreads-win32 is desired, the following variables # can be set. # # THREADS_USE_PTHREADS_WIN32 - # Setting this to true searches for the pthreads-win32 # port (since CMake 2.8.0) # # THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME # C = no exceptions (default) # (NOTE: This is the default scheme on most POSIX thread # implementations and what you should probably be using) # CE = C++ Exception Handling # SE = Structure Exception Handling (MSVC only) # (NOTE: Changing this option from the default may affect # the portability of your application. See pthreads-win32 # documentation for more details.) # #====================================================== # Example usage where threading library # is provided by the system: # # find_package(Threads REQUIRED) # add_executable(foo foo.cc) # target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) # # Example usage if pthreads-win32 is desired on Windows # or a system provided thread library: # # set(THREADS_USE_PTHREADS_WIN32 true) # find_package(Threads REQUIRED) # include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) # # add_executable(foo foo.cc) # target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) # INCLUDE (CheckIncludeFiles) INCLUDE (CheckLibraryExists) SET(Threads_FOUND FALSE) IF(WIN32 AND NOT CYGWIN AND THREADS_USE_PTHREADS_WIN32) SET(_Threads_ptwin32 true) ENDIF() # Do we have sproc? IF(CMAKE_SYSTEM MATCHES IRIX) CHECK_INCLUDE_FILES("sys/types.h;sys/prctl.h" CMAKE_HAVE_SPROC_H) ENDIF() IF(CMAKE_HAVE_SPROC_H) # We have sproc SET(CMAKE_USE_SPROC_INIT 1) ELSEIF(_Threads_ptwin32) IF(NOT DEFINED THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME) # Assign the default scheme SET(THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME "C") ELSE() # Validate the scheme specified by the user IF(NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "C" AND NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "CE" AND NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed") ENDIF() IF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC") ENDIF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") ENDIF() FIND_PATH(THREADS_PTHREADS_INCLUDE_DIR pthread.h) # Determine the library filename IF(MSVC) SET(_Threads_pthreads_libname pthreadV${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) ELSEIF(MINGW) SET(_Threads_pthreads_libname pthreadG${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) ELSE() MESSAGE(FATAL_ERROR "This should never happen") ENDIF() # Use the include path to help find the library if possible SET(_Threads_lib_paths "") IF(THREADS_PTHREADS_INCLUDE_DIR) GET_FILENAME_COMPONENT(_Threads_root_dir ${THREADS_PTHREADS_INCLUDE_DIR} PATH) SET(_Threads_lib_paths ${_Threads_root_dir}/lib) ENDIF() FIND_LIBRARY(THREADS_PTHREADS_WIN32_LIBRARY NAMES ${_Threads_pthreads_libname} PATHS ${_Threads_lib_paths} DOC "The Portable Threads Library for Win32" NO_SYSTEM_PATH ) IF(THREADS_PTHREADS_INCLUDE_DIR AND THREADS_PTHREADS_WIN32_LIBRARY) MARK_AS_ADVANCED(THREADS_PTHREADS_INCLUDE_DIR) SET(CMAKE_THREAD_LIBS_INIT ${THREADS_PTHREADS_WIN32_LIBRARY}) SET(CMAKE_HAVE_THREADS_LIBRARY 1) SET(Threads_FOUND TRUE) ENDIF() MARK_AS_ADVANCED(THREADS_PTHREADS_WIN32_LIBRARY) ELSE() # Do we have pthreads? CHECK_INCLUDE_FILES("pthread.h" CMAKE_HAVE_PTHREAD_H) IF(CMAKE_HAVE_PTHREAD_H) # # We have pthread.h # Let's check for the library now. # SET(CMAKE_HAVE_THREADS_LIBRARY) IF(NOT THREADS_HAVE_PTHREAD_ARG) # Do we have -lpthreads CHECK_LIBRARY_EXISTS(pthreads pthread_create "" CMAKE_HAVE_PTHREADS_CREATE) IF(CMAKE_HAVE_PTHREADS_CREATE) SET(CMAKE_THREAD_LIBS_INIT "-lpthreads") SET(CMAKE_HAVE_THREADS_LIBRARY 1) SET(Threads_FOUND TRUE) ENDIF() # Ok, how about -lpthread CHECK_LIBRARY_EXISTS(pthread pthread_create "" CMAKE_HAVE_PTHREAD_CREATE) IF(CMAKE_HAVE_PTHREAD_CREATE) SET(CMAKE_THREAD_LIBS_INIT "-lpthread") SET(Threads_FOUND TRUE) SET(CMAKE_HAVE_THREADS_LIBRARY 1) ENDIF() IF(CMAKE_SYSTEM MATCHES "SunOS.*") # On sun also check for -lthread CHECK_LIBRARY_EXISTS(thread thr_create "" CMAKE_HAVE_THR_CREATE) IF(CMAKE_HAVE_THR_CREATE) SET(CMAKE_THREAD_LIBS_INIT "-lthread") SET(CMAKE_HAVE_THREADS_LIBRARY 1) SET(Threads_FOUND TRUE) ENDIF() ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") ENDIF(NOT THREADS_HAVE_PTHREAD_ARG) IF(NOT CMAKE_HAVE_THREADS_LIBRARY) # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread IF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") MESSAGE(STATUS "Check if compiler accepts -pthread") TRY_RUN(THREADS_PTHREAD_ARG THREADS_HAVE_PTHREAD_ARG ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/CheckForPthreads.c CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread COMPILE_OUTPUT_VARIABLE OUTPUT) IF(THREADS_HAVE_PTHREAD_ARG) IF(THREADS_PTHREAD_ARG MATCHES "^2$") SET(Threads_FOUND TRUE) MESSAGE(STATUS "Check if compiler accepts -pthread - yes") ELSE() MESSAGE(STATUS "Check if compiler accepts -pthread - no") FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler accepts -pthread returned ${THREADS_PTHREAD_ARG} instead of 2. The compiler had the following output:\n${OUTPUT}\n\n") ENDIF() ELSE() MESSAGE(STATUS "Check if compiler accepts -pthread - no") FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n") ENDIF() ENDIF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") IF(THREADS_HAVE_PTHREAD_ARG) SET(Threads_FOUND TRUE) SET(CMAKE_THREAD_LIBS_INIT "-pthread") ENDIF() ENDIF(NOT CMAKE_HAVE_THREADS_LIBRARY) ENDIF(CMAKE_HAVE_PTHREAD_H) ENDIF() IF(CMAKE_THREAD_LIBS_INIT) SET(CMAKE_USE_PTHREADS_INIT 1) SET(Threads_FOUND TRUE) ENDIF() IF(CMAKE_SYSTEM MATCHES "Windows" AND NOT THREADS_USE_PTHREADS_WIN32) SET(CMAKE_USE_WIN32_THREADS_INIT 1) SET(Threads_FOUND TRUE) ENDIF() IF(CMAKE_USE_PTHREADS_INIT) IF(CMAKE_SYSTEM MATCHES "HP-UX-*") # Use libcma if it exists and can be used. It provides more # symbols than the plain pthread library. CMA threads # have actually been deprecated: # http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395 # http://docs.hp.com/en/947/d8.html # but we need to maintain compatibility here. # The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads # are available. CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA) IF(CMAKE_HAVE_HP_CMA) SET(CMAKE_THREAD_LIBS_INIT "-lcma") SET(CMAKE_HP_PTHREADS_INIT 1) SET(Threads_FOUND TRUE) ENDIF(CMAKE_HAVE_HP_CMA) SET(CMAKE_USE_PTHREADS_INIT 1) ENDIF() IF(CMAKE_SYSTEM MATCHES "OSF1-V*") SET(CMAKE_USE_PTHREADS_INIT 0) SET(CMAKE_THREAD_LIBS_INIT ) ENDIF() IF(CMAKE_SYSTEM MATCHES "CYGWIN_NT*") SET(CMAKE_USE_PTHREADS_INIT 1) SET(Threads_FOUND TRUE) SET(CMAKE_THREAD_LIBS_INIT ) SET(CMAKE_USE_WIN32_THREADS_INIT 0) ENDIF() ENDIF(CMAKE_USE_PTHREADS_INIT) INCLUDE(FindPackageHandleStandardArgs) IF(_Threads_ptwin32) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG THREADS_PTHREADS_WIN32_LIBRARY THREADS_PTHREADS_INCLUDE_DIR) ELSE() FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND) ENDIF() libfreenect-0.5.3/cmake_modules/Findlibusb-1.0.cmake000066400000000000000000000065641264163024100222020ustar00rootroot00000000000000# - Try to find libusb-1.0 # Once done this will define # # LIBUSB_1_FOUND - system has libusb # LIBUSB_1_INCLUDE_DIRS - the libusb include directory # LIBUSB_1_LIBRARIES - Link these to use libusb # LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb # # Adapted from cmake-modules Google Code project # # Copyright (c) 2006 Andreas Schneider # # (Changes for libusb) Copyright (c) 2008 Kyle Machulis # # Redistribution and use is allowed according to the terms of the New BSD license. # # CMake-Modules Project New BSD License # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of the CMake-Modules Project nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) # in cache already set(LIBUSB_FOUND TRUE) else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) find_path(LIBUSB_1_INCLUDE_DIR NAMES libusb.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include PATH_SUFFIXES libusb-1.0 ) find_library(LIBUSB_1_LIBRARY NAMES usb-1.0 usb PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(LIBUSB_1_INCLUDE_DIRS ${LIBUSB_1_INCLUDE_DIR} ) set(LIBUSB_1_LIBRARIES ${LIBUSB_1_LIBRARY} ) if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) set(LIBUSB_1_FOUND TRUE) endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) if (LIBUSB_1_FOUND) if (NOT libusb_1_FIND_QUIETLY) message(STATUS "Found libusb-1.0:") message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}") message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}") endif (NOT libusb_1_FIND_QUIETLY) else (LIBUSB_1_FOUND) if (libusb_1_FIND_REQUIRED) message(FATAL_ERROR "Could not find libusb") endif (libusb_1_FIND_REQUIRED) endif (LIBUSB_1_FOUND) # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES) endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) libfreenect-0.5.3/cmake_modules/SetupDirectories.cmake000066400000000000000000000014331264163024100231100ustar00rootroot00000000000000# Default installation directory, based on operating system IF (PROJECT_OS_WIN) SET (CMAKE_INSTALL_PREFIX "C:\\Program Files\\libfreenect" CACHE PATH "Installation directory") ELSE (PROJECT_OS_WIN) SET (CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation directory") ENDIF (PROJECT_OS_WIN) STRING (TOLOWER ${PROJECT_NAME} projectNameLower) SET (PROJECT_INCLUDE_INSTALL_DIR "include/${projectNameLower}") SET (PROJECT_MANPAGE_INSTALL_DIR "share/man") SET (PROJECT_LIBRARY_INSTALL_DIR "lib") MESSAGE (STATUS "${PROJECT_NAME} will be installed to ${CMAKE_INSTALL_PREFIX}") MESSAGE (STATUS "Headers will be installed to ${CMAKE_INSTALL_PREFIX}/${PROJECT_INCLUDE_INSTALL_DIR}") MESSAGE (STATUS "Libraries will be installed to ${CMAKE_INSTALL_PREFIX}/${PROJECT_LIBRARY_INSTALL_DIR}") libfreenect-0.5.3/cmake_modules/UninstallTarget.cmake.in000066400000000000000000000017371264163024100233470ustar00rootroot00000000000000if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach (file ${files}) message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") if (EXISTS "$ENV{DESTDIR}${file}") execute_process( COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" OUTPUT_VARIABLE rm_out RESULT_VARIABLE rm_retval ) if(NOT ${rm_retval} EQUAL 0) message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") endif (NOT ${rm_retval} EQUAL 0) else (EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") endif (EXISTS "$ENV{DESTDIR}${file}") endforeach(file) libfreenect-0.5.3/doc/000077500000000000000000000000001264163024100145455ustar00rootroot00000000000000libfreenect-0.5.3/doc/Doxyfile000066400000000000000000002133141264163024100162570ustar00rootroot00000000000000# Doxyfile 1.7.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libfreenect # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.1-beta # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../include \ ../doc # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.vhd *.vhdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [0,1..20]) # that doxygen will group on one line in the generated HTML documentation. # Note that a value of 0 will completely suppress the enum values from # appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif. # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES libfreenect-0.5.3/doc/DoxygenMainpage.h000066400000000000000000000033221264163024100177750ustar00rootroot00000000000000/** @mainpage libfreenect @author The OpenKinect Community - http://www.github.com/openkinect Cross-platform driver for the Microsoft Kinect Camera Website: http://www.openkinect.org @section libfreenectIntro Introduction libfreenect is an open source, cross platform development library for the Microsoft Kinect camera. It provides basic functionality to connect to the camera, set configuration values, retrieve (and in some cases decompress) images, and provides functionalty for the LED and Motor. @section libfreenectDesignOverview Design Overview libfreenect provides access to devices via two structs: - A context, which manages aspects of thread safety when using multiple devices on multiple threads. - A device, which talks to the hardware and manages transfers and configuration. Either or both of these structs are passed to the functions in order to interact with the hardware. The USB access is handled by libusb-1.0, which should work in a mostly non-blocking fashion across all platforms (see function documentation for specifics). @section libfreenectShouldIUseIt Should You Use libfreenect? The main design goal of libfreenect is to provide a simple, usable reference implementation of the Kinect USB protocol for access via non-Xbox hardware. With this in mind, the library does not contain any algorithms relevant to computer vision usages of the camera. If you are looking for machine vision algorithms, we recommend the OpenCV library, available at http://www.opencv.org If you are looking to use the kinect in a larger framework that may involve other depth sensors, we recommend the OpenNI framework, available at http://www.openni.org Note that libfreenect can be used as a hardware node in OpenNI. */ libfreenect-0.5.3/doc/astyle.conf000066400000000000000000000005771264163024100167260ustar00rootroot00000000000000# astyle config for the OpenKinect project # # To use: # astyle --options=astyle.conf -r ../src/*.c # # Due to limitations, this should not be used on header files # because it will indent all function declarations inside extern # blocks. - http://bit.ly/fG5piu indent=tab=4 min-conditional-indent=0 brackets=linux indent-switches unpad-paren pad-header lineend=linux suffix=none libfreenect-0.5.3/examples/000077500000000000000000000000001264163024100156165ustar00rootroot00000000000000libfreenect-0.5.3/examples/CMakeLists.txt000066400000000000000000000052361264163024100203640ustar00rootroot00000000000000###################################################################################### # Packages needed for examples ###################################################################################### # These examples have no external dependencies and should always build. add_executable(freenect-camtest camtest.c) add_executable(freenect-wavrecord wavrecord.c) target_link_libraries(freenect-camtest freenect) target_link_libraries(freenect-wavrecord freenect) install(TARGETS freenect-camtest freenect-wavrecord DESTINATION bin) # All viewers need pthreads and GLUT. set(THREADS_USE_PTHREADS_WIN32 true) find_package(Threads) find_package(OpenGL) find_package(GLUT) if (Threads_FOUND AND OPENGL_FOUND AND GLUT_FOUND) include_directories(${THREADS_PTHREADS_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}) add_executable(freenect-glview glview.c) add_executable(freenect-regview regview.c) add_executable(freenect-hiview hiview.c) add_executable(freenect-chunkview chunkview.c) add_executable(freenect-micview micview.c) target_link_libraries(freenect-glview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(freenect-regview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(freenect-hiview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(freenect-chunkview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(freenect-micview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) install(TARGETS freenect-glview freenect-regview freenect-hiview freenect-chunkview freenect-micview DESTINATION bin) endif () # A few examples use c_sync. if (BUILD_C_SYNC) find_package(Threads REQUIRED) include_directories(../wrappers/c_sync/) include_directories(${THREADS_PTHREADS_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}) add_executable(freenect-regtest regtest.c) add_executable(freenect-tiltdemo tiltdemo.c) target_link_libraries(freenect-regtest freenect_sync ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(freenect-tiltdemo freenect_sync ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) install(TARGETS freenect-regtest freenect-tiltdemo DESTINATION bin) if (OPENGL_FOUND AND GLUT_FOUND) add_executable(freenect-glpclview glpclview.c) target_link_libraries(freenect-glpclview freenect_sync ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) install(TARGETS freenect-glpclview DESTINATION bin) endif () endif () libfreenect-0.5.3/examples/camtest.c000066400000000000000000000070001264163024100174170ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include "libfreenect.h" #ifndef SIGQUIT // win32 compat #define SIGQUIT SIGTERM #endif void depth_cb(freenect_device* dev, void* data, uint32_t timestamp) { printf("Received depth frame at %d\n", timestamp); } void video_cb(freenect_device* dev, void* data, uint32_t timestamp) { printf("Received video frame at %d\n", timestamp); } volatile bool running = true; void signalHandler(int signal) { if (signal == SIGINT || signal == SIGTERM || signal == SIGQUIT) { running = false; } } int main(int argc, char** argv) { // Handle signals gracefully. signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); signal(SIGQUIT, signalHandler); // Initialize libfreenect. freenect_context* fn_ctx; int ret = freenect_init(&fn_ctx, NULL); if (ret < 0) return ret; // Show debug messages and use camera only. freenect_set_log_level(fn_ctx, FREENECT_LOG_DEBUG); freenect_select_subdevices(fn_ctx, FREENECT_DEVICE_CAMERA); // Find out how many devices are connected. int num_devices = ret = freenect_num_devices(fn_ctx); if (ret < 0) return ret; if (num_devices == 0) { printf("No device found!\n"); freenect_shutdown(fn_ctx); return 1; } // Open the first device. freenect_device* fn_dev; ret = freenect_open_device(fn_ctx, &fn_dev, 0); if (ret < 0) { freenect_shutdown(fn_ctx); return ret; } // Set depth and video modes. ret = freenect_set_depth_mode(fn_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_MM)); if (ret < 0) { freenect_shutdown(fn_ctx); return ret; } ret = freenect_set_video_mode(fn_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); if (ret < 0) { freenect_shutdown(fn_ctx); return ret; } // Set frame callbacks. freenect_set_depth_callback(fn_dev, depth_cb); freenect_set_video_callback(fn_dev, video_cb); // Start depth and video. ret = freenect_start_depth(fn_dev); if (ret < 0) { freenect_shutdown(fn_ctx); return ret; } ret = freenect_start_video(fn_dev); if (ret < 0) { freenect_shutdown(fn_ctx); return ret; } // Run until interruption or failure. while (running && freenect_process_events(fn_ctx) >= 0) { } printf("Shutting down\n"); // Stop everything and shutdown. freenect_stop_depth(fn_dev); freenect_stop_video(fn_dev); freenect_close_device(fn_dev); freenect_shutdown(fn_ctx); printf("Done!\n"); return 0; } libfreenect-0.5.3/examples/chunkview.c000066400000000000000000000231561264163024100177740ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2013 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include "libfreenect.h" #include #if defined(__APPLE__) #include #else #include #endif #include pthread_t freenect_thread; volatile int die = 0; int g_argc; char **g_argv; int window; pthread_mutex_t gl_backbuf_mutex = PTHREAD_MUTEX_INITIALIZER; // back: owned by libfreenect (implicit for depth) // mid: owned by callbacks, "latest frame ready" // front: owned by GL, "currently being drawn" uint8_t *depth_mid, *depth_front; GLuint gl_depth_tex; freenect_context *f_ctx; freenect_device *f_dev; int freenect_angle = 0; int freenect_led; pthread_cond_t gl_frame_cond = PTHREAD_COND_INITIALIZER; int got_depth = 0; /* Downsample and unpack pixels to 320*240 on the fly. Mind that even though we setup libfreenect to return packed data, When we process them with the chunk callback they will end up in unpacked form. Converting to mm is also an option. The best way to do it is by passing a lookup table for raw->mm as the argument to freenect_set_user. You can then access it here as the ud. */ void chunk_cb(void *buffer, void *pkt_data, int pkt_num, int pkt_size,void *ud) { if(pkt_num == 73 || pkt_num == 146) return; uint8_t *raw = (uint8_t *) pkt_data; uint16_t *frame=(uint16_t *)buffer; if(pkt_num > 219){ raw += (pkt_num-220) * 12; frame += 320 * (pkt_num-2); }else if(pkt_num > 146){ raw += (pkt_num-147) * 12 + 4; frame += 320 * (pkt_num-2); }else if(pkt_num > 73){ raw += (pkt_num-74) * 12 + 8; frame += 320 * (pkt_num-1); }else{ raw += pkt_num * 12; frame += 320 * pkt_num; } int n = 0; while(n != 40){ frame[0] = (raw[0]<<3) | (raw[1]>>5); frame[1] = ((raw[2]<<9) | (raw[3]<<1) | (raw[4]>>7) ) & 2047; frame[2] = ((raw[5]<<7) | (raw[6]>>1) ) & 2047; frame[3] = ((raw[8]<<5) | (raw[9]>>3) ) & 2047; frame[4] = (raw[11]<<3) | (raw[12]>>5); frame[5] = ((raw[13]<<9) | (raw[14]<<1) | (raw[15]>>7) ) & 2047; frame[6] = ((raw[16]<<7) | (raw[17]>>1) ) & 2047; frame[7] = ((raw[19]<<5) | (raw[20]>>3) ) & 2047; frame+=8; raw+=22; n++; } } void DrawGLScene() { pthread_mutex_lock(&gl_backbuf_mutex); while (!got_depth) { pthread_cond_wait(&gl_frame_cond, &gl_backbuf_mutex); } uint8_t *tmp; if (got_depth) { tmp = depth_front; depth_front = depth_mid; depth_mid = tmp; got_depth = 0; } pthread_mutex_unlock(&gl_backbuf_mutex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, 3, 320, 240, 0, GL_RGB, GL_UNSIGNED_BYTE, depth_front); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 0); glVertex3f(0,0,0); glTexCoord2f(1, 0); glVertex3f(320,0,0); glTexCoord2f(1, 1); glVertex3f(320,240,0); glTexCoord2f(0, 1); glVertex3f(0,240,0); glEnd(); glutSwapBuffers(); } void keyPressed(unsigned char key, int x, int y) { if (key == 27) { die = 1; pthread_join(freenect_thread, NULL); glutDestroyWindow(window); free(depth_mid); free(depth_front); // Not pthread_exit because OSX leaves a thread lying around and doesn't exit exit(0); } if (key == 'w') { freenect_angle++; if (freenect_angle > 30) { freenect_angle = 30; } } if (key == 's') { freenect_angle = 0; } if (key == 'x') { freenect_angle--; if (freenect_angle < -30) { freenect_angle = -30; } } if (key == '1') { freenect_set_led(f_dev,LED_GREEN); } if (key == '2') { freenect_set_led(f_dev,LED_RED); } if (key == '3') { freenect_set_led(f_dev,LED_YELLOW); } if (key == '4') { freenect_set_led(f_dev,LED_BLINK_GREEN); } if (key == '5') { // 5 is the same as 4 freenect_set_led(f_dev,LED_BLINK_GREEN); } if (key == '6') { freenect_set_led(f_dev,LED_BLINK_RED_YELLOW); } if (key == '0') { freenect_set_led(f_dev,LED_OFF); } freenect_set_tilt_degs(f_dev,freenect_angle); } void ReSizeGLScene(int Width, int Height) { glViewport(0,0,Width,Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (0, 320, 240, 0, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void InitGL(int Width, int Height) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0); glDepthFunc(GL_LESS); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_TEXTURE_2D); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_FLAT); glGenTextures(1, &gl_depth_tex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ReSizeGLScene(Width, Height); } void *gl_threadfunc(void *arg) { printf("GL thread\n"); glutInit(&g_argc, g_argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); glutInitWindowSize(320, 240); glutInitWindowPosition(0, 0); window = glutCreateWindow("LibFreenect"); glutDisplayFunc(&DrawGLScene); glutIdleFunc(&DrawGLScene); glutReshapeFunc(&ReSizeGLScene); glutKeyboardFunc(&keyPressed); InitGL(320, 240); glutMainLoop(); return NULL; } uint16_t t_gamma[2048]; void depth_cb(freenect_device *dev, void *v_depth, uint32_t timestamp) { int i; uint16_t *depth = (uint16_t*)v_depth; pthread_mutex_lock(&gl_backbuf_mutex); for (i=0; i<320*240; i++) { int pval = t_gamma[depth[i]]; int lb = pval & 0xff; switch (pval>>8) { case 0: depth_mid[3*i+0] = 255; depth_mid[3*i+1] = 255-lb; depth_mid[3*i+2] = 255-lb; break; case 1: depth_mid[3*i+0] = 255; depth_mid[3*i+1] = lb; depth_mid[3*i+2] = 0; break; case 2: depth_mid[3*i+0] = 255-lb; depth_mid[3*i+1] = 255; depth_mid[3*i+2] = 0; break; case 3: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 255; depth_mid[3*i+2] = lb; break; case 4: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 255-lb; depth_mid[3*i+2] = 255; break; case 5: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 0; depth_mid[3*i+2] = 255-lb; break; default: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 0; depth_mid[3*i+2] = 0; break; } } got_depth++; pthread_cond_signal(&gl_frame_cond); pthread_mutex_unlock(&gl_backbuf_mutex); } void *freenect_threadfunc(void *arg) { int accelCount = 0; freenect_set_tilt_degs(f_dev,freenect_angle); freenect_set_led(f_dev,LED_RED); freenect_set_depth_callback(f_dev, depth_cb); freenect_set_depth_mode(f_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT_PACKED)); freenect_set_depth_chunk_callback(f_dev,chunk_cb); freenect_start_depth(f_dev); printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode\n"); while (!die && freenect_process_events(f_ctx) >= 0) { //Throttle the text output if (accelCount++ >= 2000) { accelCount = 0; freenect_raw_tilt_state* state; freenect_update_tilt_state(f_dev); state = freenect_get_tilt_state(f_dev); double dx,dy,dz; freenect_get_mks_accel(state, &dx, &dy, &dz); printf("\r raw acceleration: %4d %4d %4d mks acceleration: %4f %4f %4f", state->accelerometer_x, state->accelerometer_y, state->accelerometer_z, dx, dy, dz); fflush(stdout); } } printf("\nshutting down streams...\n"); freenect_stop_depth(f_dev); freenect_close_device(f_dev); freenect_shutdown(f_ctx); printf("-- done!\n"); return NULL; } int main(int argc, char **argv) { int res; depth_mid = (uint8_t*)malloc(320*240*3); depth_front = (uint8_t*)malloc(320*240*3); printf("Kinect camera test\n"); int i; for (i=0; i<2048; i++) { float v = i/2048.0; v = powf(v, 3)* 6; t_gamma[i] = v*6*256; } g_argc = argc; g_argv = argv; if (freenect_init(&f_ctx, NULL) < 0) { printf("freenect_init() failed\n"); return 1; } freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG); freenect_select_subdevices(f_ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); int nr_devices = freenect_num_devices (f_ctx); printf ("Number of devices found: %d\n", nr_devices); int user_device_number = 0; if (argc > 1) user_device_number = atoi(argv[1]); if (nr_devices < 1) { freenect_shutdown(f_ctx); return 1; } if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) { printf("Could not open device\n"); freenect_shutdown(f_ctx); return 1; } res = pthread_create(&freenect_thread, NULL, freenect_threadfunc, NULL); if (res) { printf("pthread_create failed\n"); freenect_shutdown(f_ctx); return 1; } // OS X requires GLUT to run on the main thread gl_threadfunc(NULL); return 0; } libfreenect-0.5.3/examples/glpclview.c000066400000000000000000000137721264163024100177700ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * Andrew Miller * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "libfreenect_sync.h" #include #include #include #if defined(__APPLE__) #include #else #include #endif int window; GLuint gl_rgb_tex; int mx=-1,my=-1; // Prevous mouse coordinates int rotangles[2] = {0}; // Panning angles float zoom = 1; // zoom factor int color = 1; // Use the RGB texture or just draw it as color // Do the projection from u,v,depth to X,Y,Z directly in an opengl matrix // These numbers come from a combination of the ros kinect_node wiki, and // nicolas burrus' posts. void LoadVertexMatrix() { float fx = 594.21f; float fy = 591.04f; float a = -0.0030711f; float b = 3.3309495f; float cx = 339.5f; float cy = 242.7f; GLfloat mat[16] = { 1/fx, 0, 0, 0, 0, -1/fy, 0, 0, 0, 0, 0, a, -cx/fx, cy/fy, -1, b }; glMultMatrixf(mat); } // This matrix comes from a combination of nicolas burrus's calibration post // and some python code I haven't documented yet. void LoadRGBMatrix() { float mat[16] = { 5.34866271e+02, 3.89654806e+00, 0.00000000e+00, 1.74704200e-02, -4.70724694e+00, -5.28843603e+02, 0.00000000e+00, -1.22753400e-02, -3.19670762e+02, -2.60999685e+02, 0.00000000e+00, -9.99772000e-01, -6.98445586e+00, 3.31139785e+00, 0.00000000e+00, 1.09167360e-02 }; glMultMatrixf(mat); } void mouseMoved(int x, int y) { if (mx>=0 && my>=0) { rotangles[0] += y-my; rotangles[1] += x-mx; } mx = x; my = y; } void mousePress(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { mx = x; my = y; } if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { mx = -1; my = -1; } } void no_kinect_quit(void) { printf("Error: Kinect not connected?\n"); exit(1); } void DrawGLScene() { short *depth = 0; char *rgb = 0; uint32_t ts; if (freenect_sync_get_depth((void**)&depth, &ts, 0, FREENECT_DEPTH_11BIT) < 0) no_kinect_quit(); if (freenect_sync_get_video((void**)&rgb, &ts, 0, FREENECT_VIDEO_RGB) < 0) no_kinect_quit(); static unsigned int indices[480][640]; static short xyz[480][640][3]; int i,j; for (i = 0; i < 480; i++) { for (j = 0; j < 640; j++) { xyz[i][j][0] = j; xyz[i][j][1] = i; xyz[i][j][2] = depth[i*640+j]; indices[i][j] = i*640+j; } } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glPushMatrix(); glScalef(zoom,zoom,1); glTranslatef(0,0,-3.5); glRotatef(rotangles[0], 1,0,0); glRotatef(rotangles[1], 0,1,0); glTranslatef(0,0,1.5); LoadVertexMatrix(); // Set the projection from the XYZ to the texture image glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(1/640.0f,1/480.0f,1); LoadRGBMatrix(); LoadVertexMatrix(); glMatrixMode(GL_MODELVIEW); glPointSize(1); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_SHORT, 0, xyz); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_SHORT, 0, xyz); if (color) glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb); glPointSize(2.0f); glDrawElements(GL_POINTS, 640*480, GL_UNSIGNED_INT, indices); glPopMatrix(); glDisable(GL_TEXTURE_2D); glutSwapBuffers(); } void keyPressed(unsigned char key, int x, int y) { if (key == 27) { freenect_sync_stop(); glutDestroyWindow(window); exit(0); } if (key == 'w') zoom *= 1.1f; if (key == 's') zoom /= 1.1f; if (key == 'c') color = !color; } void ReSizeGLScene(int Width, int Height) { glViewport(0,0,Width,Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, 4/3., 0.3, 200); glMatrixMode(GL_MODELVIEW); } void InitGL(int Width, int Height) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glEnable(GL_DEPTH_TEST); glGenTextures(1, &gl_rgb_tex); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ReSizeGLScene(Width, Height); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); glutInitWindowSize(640, 480); glutInitWindowPosition(0, 0); window = glutCreateWindow("LibFreenect"); glutDisplayFunc(&DrawGLScene); glutIdleFunc(&DrawGLScene); glutReshapeFunc(&ReSizeGLScene); glutKeyboardFunc(&keyPressed); glutMotionFunc(&mouseMoved); glutMouseFunc(&mousePress); InitGL(640, 480); glutMainLoop(); return 0; } libfreenect-0.5.3/examples/glview.c000066400000000000000000000335111264163024100172620ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include "libfreenect.h" #include #if defined(__APPLE__) #include #else #include #endif #define _USE_MATH_DEFINES #include pthread_t freenect_thread; volatile int die = 0; int g_argc; char **g_argv; int window; pthread_mutex_t gl_backbuf_mutex = PTHREAD_MUTEX_INITIALIZER; // back: owned by libfreenect (implicit for depth) // mid: owned by callbacks, "latest frame ready" // front: owned by GL, "currently being drawn" uint8_t *depth_mid, *depth_front; uint8_t *rgb_back, *rgb_mid, *rgb_front; GLuint gl_depth_tex; GLuint gl_rgb_tex; GLfloat camera_angle = 0.0; int camera_rotate = 0; int tilt_changed = 0; freenect_context *f_ctx; freenect_device *f_dev; int freenect_angle = 0; int freenect_led; freenect_video_format requested_format = FREENECT_VIDEO_RGB; freenect_video_format current_format = FREENECT_VIDEO_RGB; pthread_cond_t gl_frame_cond = PTHREAD_COND_INITIALIZER; int got_rgb = 0; int got_depth = 0; void DrawGLScene() { pthread_mutex_lock(&gl_backbuf_mutex); // When using YUV_RGB mode, RGB frames only arrive at 15Hz, so we shouldn't force them to draw in lock-step. // However, this is CPU/GPU intensive when we are receiving frames in lockstep. if (current_format == FREENECT_VIDEO_YUV_RGB) { while (!got_depth && !got_rgb) { pthread_cond_wait(&gl_frame_cond, &gl_backbuf_mutex); } } else { while ((!got_depth || !got_rgb) && requested_format != current_format) { pthread_cond_wait(&gl_frame_cond, &gl_backbuf_mutex); } } if (requested_format != current_format) { pthread_mutex_unlock(&gl_backbuf_mutex); return; } uint8_t *tmp; if (got_depth) { tmp = depth_front; depth_front = depth_mid; depth_mid = tmp; got_depth = 0; } if (got_rgb) { tmp = rgb_front; rgb_front = rgb_mid; rgb_mid = tmp; got_rgb = 0; } pthread_mutex_unlock(&gl_backbuf_mutex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, depth_front); if (camera_rotate) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); freenect_raw_tilt_state* state; freenect_update_tilt_state(f_dev); state = freenect_get_tilt_state(f_dev); GLfloat x_accel_raw, x_accel,y_accel_raw,y_accel; x_accel_raw = (GLfloat)state->accelerometer_x/819.0; y_accel_raw = (GLfloat)state->accelerometer_y/819.0; // sloppy acceleration vector cleanup GLfloat accel_length = sqrt(x_accel_raw * x_accel_raw + y_accel_raw * y_accel_raw); x_accel = x_accel_raw/accel_length; y_accel = y_accel_raw/accel_length; camera_angle = atan2(y_accel,x_accel)*180/M_PI -90.0; } else { camera_angle = 0; } glLoadIdentity(); glPushMatrix(); glTranslatef((640.0/2.0),(480.0/2.0) ,0.0); glRotatef(camera_angle, 0.0, 0.0, 1.0); glTranslatef(-(640.0/2.0),-(480.0/2.0) ,0.0); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 1); glVertex3f(0,0,1.0); glTexCoord2f(1, 1); glVertex3f(640,0,1.0); glTexCoord2f(1, 0); glVertex3f(640,480,1.0); glTexCoord2f(0, 0); glVertex3f(0,480,1.0); glEnd(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); if (current_format == FREENECT_VIDEO_RGB || current_format == FREENECT_VIDEO_YUV_RGB) glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb_front); else glTexImage2D(GL_TEXTURE_2D, 0, 1, 640, 480, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, rgb_front+640*4); glPushMatrix(); glTranslatef(640+(640.0/2.0),(480.0/2.0) ,0.0); glRotatef(camera_angle, 0.0, 0.0, 1.0); glTranslatef(-(640+(640.0/2.0)),-(480.0/2.0) ,0.0); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 1); glVertex3f(640,0,0); glTexCoord2f(1, 1); glVertex3f(1280,0,0); glTexCoord2f(1, 0); glVertex3f(1280,480,0); glTexCoord2f(0, 0); glVertex3f(640,480,0); glEnd(); glPopMatrix(); glutSwapBuffers(); } void keyPressed(unsigned char key, int x, int y) { if (key == 27) { die = 1; pthread_join(freenect_thread, NULL); glutDestroyWindow(window); free(depth_mid); free(depth_front); free(rgb_back); free(rgb_mid); free(rgb_front); // Not pthread_exit because OSX leaves a thread lying around and doesn't exit exit(0); } if (key == 'w') { freenect_angle++; if (freenect_angle > 30) { freenect_angle = 30; } tilt_changed++; } if (key == 's') { freenect_angle = 0; tilt_changed++; } if (key == 'f') { if (requested_format == FREENECT_VIDEO_IR_8BIT) requested_format = FREENECT_VIDEO_RGB; else if (requested_format == FREENECT_VIDEO_RGB) requested_format = FREENECT_VIDEO_YUV_RGB; else requested_format = FREENECT_VIDEO_IR_8BIT; } if (key == 'x') { freenect_angle--; if (freenect_angle < -30) { freenect_angle = -30; } tilt_changed++; } if (key == 'e') { static freenect_flag_value auto_exposure = FREENECT_ON; freenect_set_flag(f_dev, FREENECT_AUTO_EXPOSURE, auto_exposure); auto_exposure = auto_exposure ? FREENECT_OFF : FREENECT_ON; } if (key == 'b') { static freenect_flag_value white_balance = FREENECT_ON; freenect_set_flag(f_dev, FREENECT_AUTO_WHITE_BALANCE, white_balance); white_balance = white_balance ? FREENECT_OFF : FREENECT_ON; } if (key == 'r') { static freenect_flag_value raw_color = FREENECT_ON; freenect_set_flag(f_dev, FREENECT_RAW_COLOR, raw_color); raw_color = raw_color ? FREENECT_OFF : FREENECT_ON; } if (key == 'm') { static freenect_flag_value mirror = FREENECT_ON; freenect_set_flag(f_dev, FREENECT_MIRROR_DEPTH, mirror); freenect_set_flag(f_dev, FREENECT_MIRROR_VIDEO, mirror); mirror = mirror ? FREENECT_OFF : FREENECT_ON; } if (key == 'n') { static freenect_flag_value near_mode = FREENECT_ON; freenect_set_flag(f_dev, FREENECT_NEAR_MODE, near_mode); near_mode = near_mode ? FREENECT_OFF : FREENECT_ON; } if (key == '+') { uint16_t brightness = freenect_get_ir_brightness(f_dev) + 2; freenect_set_ir_brightness(f_dev, brightness); } if (key == '-') { uint16_t brightness = freenect_get_ir_brightness(f_dev) - 2; freenect_set_ir_brightness(f_dev, brightness); } if (key == '1') { freenect_set_led(f_dev,LED_GREEN); } if (key == '2') { freenect_set_led(f_dev,LED_RED); } if (key == '3') { freenect_set_led(f_dev,LED_YELLOW); } if (key == '4') { freenect_set_led(f_dev,LED_BLINK_GREEN); } if (key == '5') { // 5 is the same as 4 freenect_set_led(f_dev,LED_BLINK_GREEN); } if (key == '6') { freenect_set_led(f_dev,LED_BLINK_RED_YELLOW); } if (key == '0') { freenect_set_led(f_dev,LED_OFF); } if (key == 'o') { if (camera_rotate) { camera_rotate = 0; glDisable(GL_DEPTH_TEST); } else { camera_rotate = 1; glEnable(GL_DEPTH_TEST); } } if (tilt_changed) { freenect_set_tilt_degs(f_dev, freenect_angle); tilt_changed = 0; } } void ReSizeGLScene(int Width, int Height) { glViewport(0,0,Width,Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (0, 1280, 0, 480, -5.0f, 5.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void InitGL(int Width, int Height) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //glClearDepth(0.0); //glDepthFunc(GL_LESS); //glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_TEXTURE_2D); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_FLAT); glGenTextures(1, &gl_depth_tex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glGenTextures(1, &gl_rgb_tex); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ReSizeGLScene(Width, Height); } void *gl_threadfunc(void *arg) { printf("GL thread\n"); glutInit(&g_argc, g_argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); glutInitWindowSize(1280, 480); glutInitWindowPosition(0, 0); window = glutCreateWindow("LibFreenect"); glutDisplayFunc(&DrawGLScene); glutIdleFunc(&DrawGLScene); glutReshapeFunc(&ReSizeGLScene); glutKeyboardFunc(&keyPressed); InitGL(1280, 480); glutMainLoop(); return NULL; } uint16_t t_gamma[2048]; void depth_cb(freenect_device *dev, void *v_depth, uint32_t timestamp) { int i; uint16_t *depth = (uint16_t*)v_depth; pthread_mutex_lock(&gl_backbuf_mutex); for (i=0; i<640*480; i++) { int pval = t_gamma[depth[i]]; int lb = pval & 0xff; switch (pval>>8) { case 0: depth_mid[3*i+0] = 255; depth_mid[3*i+1] = 255-lb; depth_mid[3*i+2] = 255-lb; break; case 1: depth_mid[3*i+0] = 255; depth_mid[3*i+1] = lb; depth_mid[3*i+2] = 0; break; case 2: depth_mid[3*i+0] = 255-lb; depth_mid[3*i+1] = 255; depth_mid[3*i+2] = 0; break; case 3: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 255; depth_mid[3*i+2] = lb; break; case 4: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 255-lb; depth_mid[3*i+2] = 255; break; case 5: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 0; depth_mid[3*i+2] = 255-lb; break; default: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 0; depth_mid[3*i+2] = 0; break; } } got_depth++; pthread_cond_signal(&gl_frame_cond); pthread_mutex_unlock(&gl_backbuf_mutex); } void rgb_cb(freenect_device *dev, void *rgb, uint32_t timestamp) { pthread_mutex_lock(&gl_backbuf_mutex); // swap buffers assert (rgb_back == rgb); rgb_back = rgb_mid; freenect_set_video_buffer(dev, rgb_back); rgb_mid = (uint8_t*)rgb; got_rgb++; pthread_cond_signal(&gl_frame_cond); pthread_mutex_unlock(&gl_backbuf_mutex); } void *freenect_threadfunc(void *arg) { int accelCount = 0; freenect_set_tilt_degs(f_dev,freenect_angle); freenect_set_led(f_dev,LED_RED); freenect_set_depth_callback(f_dev, depth_cb); freenect_set_video_callback(f_dev, rgb_cb); freenect_set_video_mode(f_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, current_format)); freenect_set_depth_mode(f_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); freenect_set_video_buffer(f_dev, rgb_back); freenect_start_depth(f_dev); freenect_start_video(f_dev); printf("'w' - tilt up, 's' - level, 'x' - tilt down, '0'-'6' - select LED mode, '+' & '-' - change IR intensity \n"); printf("'f' - change video format, 'm' - mirror video, 'o' - rotate video with accelerometer \n"); printf("'e' - auto exposure, 'b' - white balance, 'r' - raw color, 'n' - near mode (K4W only) \n"); while (!die && freenect_process_events(f_ctx) >= 0) { //Throttle the text output if (accelCount++ >= 2000) { accelCount = 0; freenect_raw_tilt_state* state; freenect_update_tilt_state(f_dev); state = freenect_get_tilt_state(f_dev); double dx,dy,dz; freenect_get_mks_accel(state, &dx, &dy, &dz); printf("\r raw acceleration: %4d %4d %4d mks acceleration: %4f %4f %4f", state->accelerometer_x, state->accelerometer_y, state->accelerometer_z, dx, dy, dz); fflush(stdout); } if (requested_format != current_format) { freenect_stop_video(f_dev); freenect_set_video_mode(f_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, requested_format)); freenect_start_video(f_dev); current_format = requested_format; } } printf("\nshutting down streams...\n"); freenect_stop_depth(f_dev); freenect_stop_video(f_dev); freenect_close_device(f_dev); freenect_shutdown(f_ctx); printf("-- done!\n"); return NULL; } int main(int argc, char **argv) { int res; depth_mid = (uint8_t*)malloc(640*480*3); depth_front = (uint8_t*)malloc(640*480*3); rgb_back = (uint8_t*)malloc(640*480*3); rgb_mid = (uint8_t*)malloc(640*480*3); rgb_front = (uint8_t*)malloc(640*480*3); printf("Kinect camera test\n"); int i; for (i=0; i<2048; i++) { float v = i/2048.0; v = powf(v, 3)* 6; t_gamma[i] = v*6*256; } g_argc = argc; g_argv = argv; if (freenect_init(&f_ctx, NULL) < 0) { printf("freenect_init() failed\n"); return 1; } freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG); freenect_select_subdevices(f_ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); int nr_devices = freenect_num_devices (f_ctx); printf ("Number of devices found: %d\n", nr_devices); int user_device_number = 0; if (argc > 1) user_device_number = atoi(argv[1]); if (nr_devices < 1) { freenect_shutdown(f_ctx); return 1; } if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) { printf("Could not open device\n"); freenect_shutdown(f_ctx); return 1; } res = pthread_create(&freenect_thread, NULL, freenect_threadfunc, NULL); if (res) { printf("pthread_create failed\n"); freenect_shutdown(f_ctx); return 1; } // OS X requires GLUT to run on the main thread gl_threadfunc(NULL); return 0; } libfreenect-0.5.3/examples/hiview.c000066400000000000000000000307111264163024100172570ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include "libfreenect.h" #include #if defined(__APPLE__) #include #else #include #endif #include pthread_t freenect_thread; volatile int die = 0; int g_argc; char **g_argv; int depth_window; int video_window; pthread_mutex_t depth_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t video_mutex = PTHREAD_MUTEX_INITIALIZER; // back: owned by libfreenect (implicit for depth) // mid: owned by callbacks, "latest frame ready" // front: owned by GL, "currently being drawn" uint8_t *depth_mid, *depth_front; uint8_t *rgb_back, *rgb_mid, *rgb_front; GLuint gl_depth_tex; GLuint gl_rgb_tex; freenect_context *f_ctx; freenect_device *f_dev; int freenect_led; freenect_video_format requested_format = FREENECT_VIDEO_RGB; freenect_video_format current_format = FREENECT_VIDEO_RGB; freenect_resolution requested_resolution = FREENECT_RESOLUTION_HIGH; freenect_resolution current_resolution = FREENECT_RESOLUTION_HIGH; pthread_cond_t gl_frame_cond = PTHREAD_COND_INITIALIZER; int got_rgb = 0; int got_depth = 0; int depth_on = 1; void DispatchDraws() { pthread_mutex_lock(&depth_mutex); if (got_depth) { glutSetWindow(depth_window); glutPostRedisplay(); } pthread_mutex_unlock(&depth_mutex); pthread_mutex_lock(&video_mutex); if (got_rgb) { glutSetWindow(video_window); glutPostRedisplay(); } pthread_mutex_unlock(&video_mutex); } void DrawDepthScene() { pthread_mutex_lock(&depth_mutex); if (got_depth) { uint8_t* tmp = depth_front; depth_front = depth_mid; depth_mid = tmp; got_depth = 0; } pthread_mutex_unlock(&depth_mutex); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, depth_front); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 0); glVertex3f(0,0,0); glTexCoord2f(1, 0); glVertex3f(640,0,0); glTexCoord2f(1, 1); glVertex3f(640,480,0); glTexCoord2f(0, 1); glVertex3f(0,480,0); glEnd(); glutSwapBuffers(); } void DrawVideoScene() { if (requested_format != current_format || requested_resolution != current_resolution) { return; } pthread_mutex_lock(&video_mutex); freenect_frame_mode frame_mode = freenect_get_current_video_mode(f_dev); if (got_rgb) { uint8_t *tmp = rgb_front; rgb_front = rgb_mid; rgb_mid = tmp; got_rgb = 0; } pthread_mutex_unlock(&video_mutex); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); if (current_format == FREENECT_VIDEO_RGB || current_format == FREENECT_VIDEO_YUV_RGB) { glTexImage2D(GL_TEXTURE_2D, 0, 3, frame_mode.width, frame_mode.height, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb_front); } else { glTexImage2D(GL_TEXTURE_2D, 0, 1, frame_mode.width, frame_mode.height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, rgb_front); } glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 0); glVertex3f(0,0,0); glTexCoord2f(1, 0); glVertex3f(frame_mode.width,0,0); glTexCoord2f(1, 1); glVertex3f(frame_mode.width,frame_mode.height,0); glTexCoord2f(0, 1); glVertex3f(0,frame_mode.height,0); glEnd(); glutSwapBuffers(); } void keyPressed(unsigned char key, int x, int y) { if (key == 27) { die = 1; pthread_join(freenect_thread, NULL); glutDestroyWindow(depth_window); glutDestroyWindow(video_window); free(depth_mid); free(depth_front); free(rgb_back); free(rgb_mid); free(rgb_front); // Not pthread_exit because OSX leaves a thread lying around and doesn't exit exit(0); } if (key == 'f') { // Cycle through: // 1) 1280x1024 RGB // 2) 1280x1024 IR // 3) 640x480 RGB // 4) 640x480 YUV // 5) 640x480 IR if(current_resolution == FREENECT_RESOLUTION_HIGH) { if(current_format == FREENECT_VIDEO_RGB) { requested_format = FREENECT_VIDEO_IR_8BIT; // Since we can't stream the high-res IR while running the depth stream, // we force the depth stream off when we reach this res in the cycle. freenect_stop_depth(f_dev); memset(depth_mid, 0, 640*480*3); // black out the depth camera got_depth++; depth_on = 0; } else if (current_format == FREENECT_VIDEO_IR_8BIT) { requested_format = FREENECT_VIDEO_RGB; requested_resolution = FREENECT_RESOLUTION_MEDIUM; } } else if (current_resolution == FREENECT_RESOLUTION_MEDIUM) { if(current_format == FREENECT_VIDEO_RGB) { requested_format = FREENECT_VIDEO_YUV_RGB; } else if (current_format == FREENECT_VIDEO_YUV_RGB) { requested_format = FREENECT_VIDEO_IR_8BIT; } else if (current_format == FREENECT_VIDEO_IR_8BIT) { requested_format = FREENECT_VIDEO_RGB; requested_resolution = FREENECT_RESOLUTION_HIGH; } } glutSetWindow(video_window); freenect_frame_mode s = freenect_find_video_mode(requested_resolution, requested_format); glutReshapeWindow(s.width, s.height); } if (key == 'd') { // Toggle depth camera. if(depth_on) { freenect_stop_depth(f_dev); memset(depth_mid, 0, 640*480*3); // black out the depth camera got_depth++; depth_on = 0; } else { freenect_start_depth(f_dev); depth_on = 1; } } } void ReSizeGLScene(int Width, int Height) { glViewport(0,0,Width,Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (0, Width, Height, 0, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); } void InitGL(int Width, int Height) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0); glDepthFunc(GL_LESS); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_SMOOTH); glGenTextures(1, &gl_depth_tex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glGenTextures(1, &gl_rgb_tex); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ReSizeGLScene(Width, Height); } void *gl_threadfunc(void *arg) { printf("GL thread\n"); glutInit(&g_argc, g_argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); glutInitWindowSize(640, 480); glutInitWindowPosition(0, 0); depth_window = glutCreateWindow("Depth"); glutDisplayFunc(&DrawDepthScene); glutIdleFunc(&DispatchDraws); glutKeyboardFunc(&keyPressed); InitGL(640, 480); freenect_frame_mode mode = freenect_find_video_mode(current_resolution, current_format); glutInitWindowPosition(640,0); glutInitWindowSize(mode.width, mode.height); video_window = glutCreateWindow("Video"); glutDisplayFunc(&DrawVideoScene); glutIdleFunc(&DispatchDraws); glutReshapeFunc(&ReSizeGLScene); glutKeyboardFunc(&keyPressed); InitGL(640, 480); ReSizeGLScene(mode.width, mode.height); glutMainLoop(); return NULL; } uint16_t t_gamma[2048]; void depth_cb(freenect_device *dev, void *v_depth, uint32_t timestamp) { int i; uint16_t *depth = (uint16_t*)v_depth; pthread_mutex_lock(&depth_mutex); for (i=0; i<640*480; i++) { int pval = t_gamma[depth[i]]; int lb = pval & 0xff; switch (pval>>8) { case 0: depth_mid[3*i+0] = 255; depth_mid[3*i+1] = 255-lb; depth_mid[3*i+2] = 255-lb; break; case 1: depth_mid[3*i+0] = 255; depth_mid[3*i+1] = lb; depth_mid[3*i+2] = 0; break; case 2: depth_mid[3*i+0] = 255-lb; depth_mid[3*i+1] = 255; depth_mid[3*i+2] = 0; break; case 3: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 255; depth_mid[3*i+2] = lb; break; case 4: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 255-lb; depth_mid[3*i+2] = 255; break; case 5: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 0; depth_mid[3*i+2] = 255-lb; break; default: depth_mid[3*i+0] = 0; depth_mid[3*i+1] = 0; depth_mid[3*i+2] = 0; break; } } got_depth++; pthread_mutex_unlock(&depth_mutex); } void video_cb(freenect_device *dev, void *rgb, uint32_t timestamp) { pthread_mutex_lock(&video_mutex); // swap buffers assert (rgb_back == rgb); rgb_back = rgb_mid; freenect_set_video_buffer(dev, rgb_back); rgb_mid = (uint8_t*)rgb; got_rgb++; pthread_mutex_unlock(&video_mutex); } void *freenect_threadfunc(void *arg) { freenect_set_led(f_dev,LED_RED); freenect_set_depth_callback(f_dev, depth_cb); freenect_set_video_callback(f_dev, video_cb); freenect_set_video_mode(f_dev, freenect_find_video_mode(current_resolution, current_format)); freenect_set_depth_mode(f_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); rgb_back = (uint8_t*)malloc(freenect_find_video_mode(current_resolution, current_format).bytes); rgb_mid = (uint8_t*)malloc(freenect_find_video_mode(current_resolution, current_format).bytes); rgb_front = (uint8_t*)malloc(freenect_find_video_mode(current_resolution, current_format).bytes); freenect_set_video_buffer(f_dev, rgb_back); freenect_start_depth(f_dev); freenect_start_video(f_dev); int status = 0; while (!die && status >= 0) { status = freenect_process_events(f_ctx); if (requested_format != current_format || requested_resolution != current_resolution) { freenect_stop_video(f_dev); freenect_set_video_mode(f_dev, freenect_find_video_mode(requested_resolution, requested_format)); pthread_mutex_lock(&video_mutex); free(rgb_back); free(rgb_mid); free(rgb_front); rgb_back = (uint8_t*)malloc(freenect_find_video_mode(requested_resolution, requested_format).bytes); rgb_mid = (uint8_t*)malloc(freenect_find_video_mode(requested_resolution, requested_format).bytes); rgb_front = (uint8_t*)malloc(freenect_find_video_mode(requested_resolution, requested_format).bytes); current_format = requested_format; current_resolution = requested_resolution; pthread_mutex_unlock(&video_mutex); freenect_set_video_buffer(f_dev, rgb_back); freenect_start_video(f_dev); } } if (status < 0) { printf("Something went terribly wrong. Aborting.\n"); return NULL; } printf("\nshutting down streams...\n"); freenect_stop_depth(f_dev); freenect_stop_video(f_dev); freenect_close_device(f_dev); freenect_shutdown(f_ctx); printf("-- done!\n"); return NULL; } int main(int argc, char **argv) { int res; depth_mid = (uint8_t*)malloc(640*480*3); depth_front = (uint8_t*)malloc(640*480*3); printf("Kinect camera test\n"); int i; for (i=0; i<2048; i++) { float v = i/2048.0; v = powf(v, 3)* 6; t_gamma[i] = v*6*256; } g_argc = argc; g_argv = argv; if (freenect_init(&f_ctx, NULL) < 0) { printf("freenect_init() failed\n"); return 1; } freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG); freenect_select_subdevices(f_ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); int nr_devices = freenect_num_devices (f_ctx); printf ("Number of devices found: %d\n", nr_devices); int user_device_number = 0; if (argc > 1) user_device_number = atoi(argv[1]); if (nr_devices < 1) { freenect_shutdown(f_ctx); return 1; } if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) { printf("Could not open device\n"); freenect_shutdown(f_ctx); return 1; } res = pthread_create(&freenect_thread, NULL, freenect_threadfunc, NULL); if (res) { printf("pthread_create failed\n"); freenect_shutdown(f_ctx); return 1; } // OS X requires GLUT to run on the main thread gl_threadfunc(NULL); return 0; } libfreenect-0.5.3/examples/micview.c000066400000000000000000000156651264163024100174420ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "libfreenect_audio.h" #include #include #include #include #if defined(__APPLE__) #include #else #include #endif pthread_t freenect_thread; volatile int die = 0; static freenect_context* f_ctx; static freenect_device* f_dev; typedef struct { int32_t* buffers[4]; int max_samples; int current_idx; // index to the oldest data in the buffer (equivalently, where the next new data will be placed) int new_data; } capture; capture state; int paused = 0; pthread_mutex_t audiobuf_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t audiobuf_cond = PTHREAD_COND_INITIALIZER; int win_h, win_w; void in_callback(freenect_device* dev, int num_samples, int32_t* mic1, int32_t* mic2, int32_t* mic3, int32_t* mic4, int16_t* cancelled, void *unknown) { pthread_mutex_lock(&audiobuf_mutex); capture* c = (capture*)freenect_get_user(dev); if(num_samples < c->max_samples - c->current_idx) { memcpy(&(c->buffers[0][c->current_idx]), mic1, num_samples*sizeof(int32_t)); memcpy(&(c->buffers[1][c->current_idx]), mic2, num_samples*sizeof(int32_t)); memcpy(&(c->buffers[2][c->current_idx]), mic3, num_samples*sizeof(int32_t)); memcpy(&(c->buffers[3][c->current_idx]), mic4, num_samples*sizeof(int32_t)); } else { int first = c->max_samples - c->current_idx; int left = num_samples - first; memcpy(&(c->buffers[0][c->current_idx]), mic1, first*sizeof(int32_t)); memcpy(&(c->buffers[1][c->current_idx]), mic2, first*sizeof(int32_t)); memcpy(&(c->buffers[2][c->current_idx]), mic3, first*sizeof(int32_t)); memcpy(&(c->buffers[3][c->current_idx]), mic4, first*sizeof(int32_t)); memcpy(c->buffers[0], &mic1[first], left*sizeof(int32_t)); memcpy(c->buffers[1], &mic2[first], left*sizeof(int32_t)); memcpy(c->buffers[2], &mic3[first], left*sizeof(int32_t)); memcpy(c->buffers[3], &mic4[first], left*sizeof(int32_t)); } c->current_idx = (c->current_idx + num_samples) % c->max_samples; c->new_data = 1; pthread_cond_signal(&audiobuf_cond); pthread_mutex_unlock(&audiobuf_mutex); } void* freenect_threadfunc(void* arg) { while(!die && freenect_process_events(f_ctx) >= 0) { // If we did anything else in the freenect thread, it might go here. } freenect_stop_audio(f_dev); freenect_close_device(f_dev); freenect_shutdown(f_ctx); return NULL; } void DrawMicData() { if (paused) return; pthread_mutex_lock(&audiobuf_mutex); while(!state.new_data) pthread_cond_wait(&audiobuf_cond, &audiobuf_mutex); state.new_data = 0; // Draw: glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float xIncr = (float)win_w / state.max_samples; float x = 0.; int i; int base_idx = state.current_idx; // Technically, we should hold the lock until we're done actually drawing // the lines, but this is sufficient to ensure that the drawings align // provided we don't reallocate buffers. pthread_mutex_unlock(&audiobuf_mutex); // This is kinda slow. It should be possible to compile each sample // window into a glCallList, but that's overly complex. int mic; for(mic = 0; mic < 4; mic++) { glBegin(GL_LINE_STRIP); glColor4f(1.0f, 1.0f, 1.0f, 0.7f); for(x = 0, i = 0; i < state.max_samples; i++) { glVertex3f(x, ((float)win_h * (float)(2*mic + 1) / 8. ) + (float)(state.buffers[mic][(base_idx + i) % state.max_samples]) * ((float)win_h/4) /2147483647. , 0); x += xIncr; } glEnd(); } glutSwapBuffers(); } void Reshape(int w, int h) { win_w = w; win_h = h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, (float)w, (float)h, 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void Keyboard(unsigned char key, int x, int y) { if(key == 'q') { die = 1; pthread_exit(NULL); } if(key == 32) { paused = !paused; } } int main(int argc, char** argv) { if (freenect_init(&f_ctx, NULL) < 0) { printf("freenect_init() failed\n"); return 1; } freenect_set_log_level(f_ctx, FREENECT_LOG_INFO); freenect_select_subdevices(f_ctx, FREENECT_DEVICE_AUDIO); int nr_devices = freenect_num_devices (f_ctx); printf ("Number of devices found: %d\n", nr_devices); if (nr_devices < 1) { freenect_shutdown(f_ctx); return 1; } int user_device_number = 0; if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) { printf("Could not open device\n"); freenect_shutdown(f_ctx); return 1; } state.max_samples = 256 * 60; state.current_idx = 0; state.buffers[0] = (int32_t*)malloc(state.max_samples * sizeof(int32_t)); state.buffers[1] = (int32_t*)malloc(state.max_samples * sizeof(int32_t)); state.buffers[2] = (int32_t*)malloc(state.max_samples * sizeof(int32_t)); state.buffers[3] = (int32_t*)malloc(state.max_samples * sizeof(int32_t)); memset(state.buffers[0], 0, state.max_samples * sizeof(int32_t)); memset(state.buffers[1], 0, state.max_samples * sizeof(int32_t)); memset(state.buffers[2], 0, state.max_samples * sizeof(int32_t)); memset(state.buffers[3], 0, state.max_samples * sizeof(int32_t)); freenect_set_user(f_dev, &state); freenect_set_audio_in_callback(f_dev, in_callback); freenect_start_audio(f_dev); int res = pthread_create(&freenect_thread, NULL, freenect_threadfunc, NULL); if (res) { printf("pthread_create failed\n"); freenect_shutdown(f_ctx); return 1; } printf("This is the libfreenect microphone waveform viewer. Press 'q' to quit or spacebar to pause/unpause the view.\n"); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA ); glutInitWindowSize(800, 600); glutInitWindowPosition(0, 0); glutCreateWindow("Microphones"); glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Reshape(800, 600); glutReshapeFunc(Reshape); glutDisplayFunc(DrawMicData); glutIdleFunc(DrawMicData); glutKeyboardFunc(Keyboard); glutMainLoop(); return 0; } libfreenect-0.5.3/examples/regtest.c000066400000000000000000000053521264163024100174440ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include "libfreenect.h" #include "libfreenect_sync.h" FILE *open_dump(const char *filename) { FILE* fp = fopen(filename, "w"); if (fp == NULL) { fprintf(stderr, "Error: Cannot open file [%s]\n", filename); exit(1); } printf("%s\n", filename); return fp; } void dump_depth(FILE *fp, void *data, unsigned int width, unsigned int height) { fprintf(fp, "P5 %u %u 65535\n", width, height); fwrite(data, width * height * 2, 1, fp); } void dump_rgb(FILE *fp, void *data, unsigned int width, unsigned int height) { fprintf(fp, "P6 %u %u 255\n", width, height); fwrite(data, width * height * 3, 1, fp); } void no_kinect_quit(void) { fprintf(stderr, "Error: Kinect not connected?\n"); exit(1); } int main(void) { short *depth = 0; char *rgb = 0; uint32_t ts; FILE *fp; int ret; ret = freenect_sync_get_video((void**)&rgb, &ts, 0, FREENECT_VIDEO_RGB); if (ret < 0) no_kinect_quit(); fp = open_dump("registration_test_rgb.ppm"); dump_rgb(fp, rgb, 640, 480); fclose(fp); ret = freenect_sync_get_depth((void**)&depth, &ts, 0, FREENECT_DEPTH_11BIT); if (ret < 0) no_kinect_quit(); fp = open_dump("registration_test_depth_raw.pgm"); dump_depth(fp, depth, 640, 480); fclose(fp); ret = freenect_sync_get_depth((void**)&depth, &ts, 0, FREENECT_DEPTH_REGISTERED); if (ret < 0) no_kinect_quit(); fp = open_dump("registration_test_depth_registered.pgm"); dump_depth(fp, depth, 640, 480); fclose(fp); ret = freenect_sync_get_depth((void**)&depth, &ts, 0, FREENECT_DEPTH_MM); if (ret < 0) no_kinect_quit(); fp = open_dump("registration_test_depth_mm.pgm"); dump_depth(fp, depth, 640, 480); fclose(fp); return 0; } libfreenect-0.5.3/examples/regview.c000066400000000000000000000224011264163024100174310ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include "libfreenect.h" #include #include #if defined(__APPLE__) #include #else #include #endif pthread_t freenect_thread; volatile int die = 0; int g_argc; char **g_argv; int window; pthread_mutex_t gl_backbuf_mutex = PTHREAD_MUTEX_INITIALIZER; // back: owned by libfreenect (implicit for depth) // mid: owned by callbacks, "latest frame ready" // front: owned by GL, "currently being drawn" uint8_t *depth_mid, *depth_front; uint8_t *rgb_back, *rgb_mid, *rgb_front; GLuint gl_depth_tex; GLuint gl_rgb_tex; freenect_context *f_ctx; freenect_device *f_dev; int freenect_angle = 0; int freenect_led; pthread_cond_t gl_frame_cond = PTHREAD_COND_INITIALIZER; int got_rgb = 0; int got_depth = 0; int frame = 0; int my_ftime = 0; double fps = 0; void idle() { pthread_mutex_lock(&gl_backbuf_mutex); // When using YUV_RGB mode, RGB frames only arrive at 15Hz, so we shouldn't force them to draw in lock-step. // However, this is CPU/GPU intensive when we are receiving frames in lockstep. while (!got_depth && !got_rgb) { pthread_cond_wait(&gl_frame_cond, &gl_backbuf_mutex); } if (!got_depth || !got_rgb) { pthread_mutex_unlock(&gl_backbuf_mutex); return; } pthread_mutex_unlock(&gl_backbuf_mutex); glutPostRedisplay(); } void DrawGLScene() { uint8_t *tmp; pthread_mutex_lock(&gl_backbuf_mutex); if (got_depth) { tmp = depth_front; depth_front = depth_mid; depth_mid = tmp; got_depth = 0; } if (got_rgb) { tmp = rgb_front; rgb_front = rgb_mid; rgb_mid = tmp; got_rgb = 0; } pthread_mutex_unlock(&gl_backbuf_mutex); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb_front); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 0); glVertex3f(0,0,0); glTexCoord2f(1, 0); glVertex3f(640,0,0); glTexCoord2f(1, 1); glVertex3f(640,480,0); glTexCoord2f(0, 1); glVertex3f(0,480,0); glEnd(); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, 4, 640, 480, 0, GL_RGBA, GL_UNSIGNED_BYTE, depth_front); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0, 0); glVertex3f(0,0,0); glTexCoord2f(1, 0); glVertex3f(640,0,0); glTexCoord2f(1, 1); glVertex3f(640,480,0); glTexCoord2f(0, 1); glVertex3f(0,480,0); glEnd(); glutSwapBuffers(); frame++; if (frame % 30 == 0) { int ms = glutGet(GLUT_ELAPSED_TIME); fps = 30.0/((ms - my_ftime)/1000.0); my_ftime = ms; } } void keyPressed(unsigned char key, int x, int y) { if (key == 27 || key == 'q') { die = 1; pthread_join(freenect_thread, NULL); pthread_cond_signal(&gl_frame_cond); glutDestroyWindow(window); free(depth_mid); free(depth_front); free(rgb_back); free(rgb_mid); free(rgb_front); // Not pthread_exit because OSX leaves a thread lying around and doesn't exit exit(0); } } void ReSizeGLScene(int Width, int Height) { glViewport(0,0,Width,Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (0, 640, 480, 0, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void InitGL(int Width, int Height) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0); glDepthFunc(GL_LESS); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_TEXTURE_2D); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_FLAT); glGenTextures(1, &gl_depth_tex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glGenTextures(1, &gl_rgb_tex); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ReSizeGLScene(Width, Height); } void *gl_threadfunc(void *arg) { printf("GL thread\n"); glutInit(&g_argc, g_argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); glutInitWindowSize(640, 480); glutInitWindowPosition(0, 0); window = glutCreateWindow("libfreenect Registration viewer"); glutDisplayFunc(&DrawGLScene); glutIdleFunc(&idle); glutReshapeFunc(&ReSizeGLScene); glutKeyboardFunc(&keyPressed); InitGL(640, 480); glutMainLoop(); return NULL; } uint16_t t_gamma[10000]; void depth_cb(freenect_device *dev, void *v_depth, uint32_t timestamp) { int i; uint16_t *depth = (uint16_t*)v_depth; pthread_mutex_lock(&gl_backbuf_mutex); for (i=0; i<640*480; i++) { //if (depth[i] >= 2048) continue; int pval = t_gamma[depth[i]] / 4; int lb = pval & 0xff; depth_mid[4*i+3] = 128; // default alpha value if (depth[i] == 0) depth_mid[4*i+3] = 0; // remove anything without depth value switch (pval>>8) { case 0: depth_mid[4*i+0] = 255; depth_mid[4*i+1] = 255-lb; depth_mid[4*i+2] = 255-lb; break; case 1: depth_mid[4*i+0] = 255; depth_mid[4*i+1] = lb; depth_mid[4*i+2] = 0; break; case 2: depth_mid[4*i+0] = 255-lb; depth_mid[4*i+1] = 255; depth_mid[4*i+2] = 0; break; case 3: depth_mid[4*i+0] = 0; depth_mid[4*i+1] = 255; depth_mid[4*i+2] = lb; break; case 4: depth_mid[4*i+0] = 0; depth_mid[4*i+1] = 255-lb; depth_mid[4*i+2] = 255; break; case 5: depth_mid[4*i+0] = 0; depth_mid[4*i+1] = 0; depth_mid[4*i+2] = 255-lb; break; default: depth_mid[4*i+0] = 0; depth_mid[4*i+1] = 0; depth_mid[4*i+2] = 0; depth_mid[4*i+3] = 0; break; } } got_depth++; pthread_cond_signal(&gl_frame_cond); pthread_mutex_unlock(&gl_backbuf_mutex); } void rgb_cb(freenect_device *dev, void *rgb, uint32_t timestamp) { pthread_mutex_lock(&gl_backbuf_mutex); // swap buffers assert (rgb_back == rgb); rgb_back = rgb_mid; freenect_set_video_buffer(dev, rgb_back); rgb_mid = (uint8_t*)rgb; got_rgb++; pthread_cond_signal(&gl_frame_cond); pthread_mutex_unlock(&gl_backbuf_mutex); } void *freenect_threadfunc(void *arg) { freenect_set_depth_callback(f_dev, depth_cb); freenect_set_video_callback(f_dev, rgb_cb); freenect_set_video_mode(f_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); freenect_set_depth_mode(f_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_REGISTERED)); freenect_set_video_buffer(f_dev, rgb_back); freenect_start_depth(f_dev); freenect_start_video(f_dev); printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode, 'f'-video format\n"); while (!die) { int res = freenect_process_events(f_ctx); if (res < 0 && res != -10) { printf("\nError %d received from libusb - aborting.\n",res); break; } } printf("\nshutting down streams...\n"); freenect_stop_depth(f_dev); freenect_stop_video(f_dev); freenect_close_device(f_dev); freenect_shutdown(f_ctx); printf("-- done!\n"); return NULL; } int main(int argc, char **argv) { int res; depth_mid = (uint8_t*)malloc(640*480*4); depth_front = (uint8_t*)malloc(640*480*4); rgb_back = (uint8_t*)malloc(640*480*3); rgb_mid = (uint8_t*)malloc(640*480*3); rgb_front = (uint8_t*)malloc(640*480*3); printf("Kinect camera test\n"); int i; for (i=0; i<10000; i++) { float v = i/2048.0; v = powf(v, 3)* 6; t_gamma[i] = v*6*256; } g_argc = argc; g_argv = argv; if (freenect_init(&f_ctx, NULL) < 0) { printf("freenect_init() failed\n"); return 1; } freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG); freenect_select_subdevices(f_ctx, (freenect_device_flags)(FREENECT_DEVICE_CAMERA)); int nr_devices = freenect_num_devices (f_ctx); printf ("Number of devices found: %d\n", nr_devices); int user_device_number = 0; if (argc > 1) user_device_number = atoi(argv[1]); if (nr_devices < 1) { freenect_shutdown(f_ctx); return 1; } if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) { printf("Could not open device\n"); freenect_shutdown(f_ctx); return 1; } res = pthread_create(&freenect_thread, NULL, freenect_threadfunc, NULL); if (res) { printf("pthread_create failed\n"); freenect_shutdown(f_ctx); return 1; } // OS X requires GLUT to run on the main thread gl_threadfunc(NULL); return 0; } libfreenect-0.5.3/examples/tiltdemo.c000066400000000000000000000104701264163024100176050ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * Andrew Miller * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "libfreenect_sync.h" #include #include #include #ifndef _WIN32 #include #else // Microsoft Visual C++ does not provide the header, but most of // its contents can be found within the header: #include // except for the UNIX sleep() function that has to be emulated: #include // http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html // According to the link above, the semantics of UNIX sleep() is as follows: // "If sleep() returns because the requested time has elapsed, the value // returned shall be 0. If sleep() returns due to delivery of a signal, the // return value shall be the "unslept" amount (the requested time minus the // time actually slept) in seconds." // The following function does not implement the return semantics, but // will do for now... A proper implementation would require Performance // Counters before and after the forward call to the Windows Sleep()... unsigned sleep(unsigned seconds) { Sleep(seconds*1000); // The Windows Sleep operates on milliseconds return(0); } // Note for MinGW-gcc users: MinGW-gcc also does not provide the UNIX sleep() // function within , but it does provide usleep(); trivial wrapping // of sleep() aroung usleep() is possible, however the usleep() documentation // (http://docs.hp.com/en/B2355-90682/usleep.2.html) clearly states that: // "The useconds argument must be less than 1,000,000. (...) // (...) The usleep() function may fail if: // [EINVAL] // The time interval specified 1,000,000 or more microseconds." // which means that something like below can be potentially dangerous: // unsigned sleep(unsigned seconds) // { // usleep(seconds*1000000); // The usleep operates on microseconds // return(0); // } // So, it is strongly advised to stick with the _WIN32/_MSC_VER // http://www.xinotes.org/notes/note/439/ #endif//_WIN32 /* This is a simple demo. It connects to the kinect and plays with the motor, the accelerometers, and the LED. It doesn't do anything with images. And, unlike the other examples, no OpenGL is required! So, this should serve as the reference example for working with the motor, accelerometers, and LEDs. */ void no_kinect_quit(void) { printf("Error: Kinect not connected?\n"); exit(1); } int main(int argc, char *argv[]) { srand(time(0)); while (1) { // Pick a random tilt and a random LED state freenect_led_options led = (freenect_led_options) (rand() % 6); // explicit cast int tilt = (rand() % 30)-15; freenect_raw_tilt_state *state = 0; double dx, dy, dz; // Set the LEDs to one of the possible states if (freenect_sync_set_led(led, 0)) no_kinect_quit(); // Set the tilt angle (in degrees) if (freenect_sync_set_tilt_degs(tilt, 0)) no_kinect_quit(); // Get the raw accelerometer values and tilt data if (freenect_sync_get_tilt_state(&state, 0)) no_kinect_quit(); // Get the processed accelerometer values (calibrated to gravity) freenect_get_mks_accel(state, &dx, &dy, &dz); printf("led[%d] tilt[%d] accel[%lf,%lf,%lf]\n", led, tilt, dx,dy,dz); sleep(3); } } libfreenect-0.5.3/examples/wavrecord.c000066400000000000000000000117021264163024100177570ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "libfreenect_audio.h" #include #include static freenect_context* f_ctx; static freenect_device* f_dev; int die = 0; char wavheader[] = { 0x52, 0x49, 0x46, 0x46, // ChunkID = "RIFF" 0x00, 0x00, 0x00, 0x00, // Chunksize (will be overwritten later) 0x57, 0x41, 0x56, 0x45, // Format = "WAVE" 0x66, 0x6d, 0x74, 0x20, // Subchunk1ID = "fmt " 0x10, 0x00, 0x00, 0x00, // Subchunk1Size = 16 0x01, 0x00, 0x01, 0x00, // AudioFormat = 1 (linear quantization) | NumChannels = 1 0x80, 0x3e, 0x00, 0x00, // SampleRate = 16000 Hz 0x00, 0xfa, 0x00, 0x00, // ByteRate = SampleRate * NumChannels * BitsPerSample/8 = 64000 0x04, 0x00, 0x20, 0x00, // BlockAlign = NumChannels * BitsPerSample/8 = 4 | BitsPerSample = 32 0x64, 0x61, 0x74, 0x61, // Subchunk2ID = "data" 0x00, 0x00, 0x00, 0x00, // Subchunk2Size = NumSamples * NumChannels * BitsPerSample / 8 (will be overwritten later) }; typedef struct { FILE* logfiles[4]; int samples; } capture; void in_callback(freenect_device* dev, int num_samples, int32_t* mic1, int32_t* mic2, int32_t* mic3, int32_t* mic4, int16_t* cancelled, void *unknown) { capture* c = (capture*)freenect_get_user(dev); fwrite(mic1, 1, num_samples*sizeof(int32_t), c->logfiles[0]); fwrite(mic2, 1, num_samples*sizeof(int32_t), c->logfiles[1]); fwrite(mic3, 1, num_samples*sizeof(int32_t), c->logfiles[2]); fwrite(mic4, 1, num_samples*sizeof(int32_t), c->logfiles[3]); c->samples += num_samples; printf("Sample received. Total samples recorded: %d\n", c->samples); } void cleanup(int sig) { printf("Caught SIGINT, cleaning up\n"); die = 1; } int main(int argc, char** argv) { if (freenect_init(&f_ctx, NULL) < 0) { printf("freenect_init() failed\n"); return 1; } freenect_set_log_level(f_ctx, FREENECT_LOG_SPEW); freenect_select_subdevices(f_ctx, FREENECT_DEVICE_AUDIO); int nr_devices = freenect_num_devices (f_ctx); printf ("Number of devices found: %d\n", nr_devices); if (nr_devices < 1) { freenect_shutdown(f_ctx); return 1; } int user_device_number = 0; if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) { printf("Could not open device\n"); freenect_shutdown(f_ctx); return 1; } capture state; state.samples = 0; state.logfiles[0] = fopen("channel1.wav", "wb"); state.logfiles[1] = fopen("channel2.wav", "wb"); state.logfiles[2] = fopen("channel3.wav", "wb"); state.logfiles[3] = fopen("channel4.wav", "wb"); fwrite(wavheader, 1, 44, state.logfiles[0]); fwrite(wavheader, 1, 44, state.logfiles[1]); fwrite(wavheader, 1, 44, state.logfiles[2]); fwrite(wavheader, 1, 44, state.logfiles[3]); freenect_set_user(f_dev, &state); freenect_set_audio_in_callback(f_dev, in_callback); freenect_start_audio(f_dev); signal(SIGINT, cleanup); while(!die && freenect_process_events(f_ctx) >= 0) { // If we did anything else, it might go here. // Alternately, we might split off another thread // to do this loop while the main thread did something // interesting. } // Make the WAV header valid for each of the four files int i; for(i = 0; i < 4 ; i++) { char buf[4]; fseek(state.logfiles[i], 4, SEEK_SET); // Write ChunkSize = 36 + subchunk2size int chunksize = state.samples * 4 + 36; buf[0] = (chunksize & 0x000000ff); buf[1] = (chunksize & 0x0000ff00) >> 8; buf[2] = (chunksize & 0x00ff0000) >> 16; buf[3] = (chunksize & 0xff000000) >> 24; fwrite(buf, 1, 4,state.logfiles[i]); fseek(state.logfiles[i], 40, SEEK_SET); // Write Subchunk2Size = NumSamples * NumChannels (1) * BitsPerSample/8 (4) int subchunk2size = state.samples * 4; buf[0] = (subchunk2size & 0x000000ff); buf[1] = (subchunk2size & 0x0000ff00) >> 8; buf[2] = (subchunk2size & 0x00ff0000) >> 16; buf[3] = (subchunk2size & 0xff000000) >> 24; fwrite(buf, 1, 4,state.logfiles[i]); fclose(state.logfiles[i]); } freenect_shutdown(f_ctx); return 0; } libfreenect-0.5.3/fakenect/000077500000000000000000000000001264163024100155605ustar00rootroot00000000000000libfreenect-0.5.3/fakenect/CMakeLists.txt000066400000000000000000000017641264163024100203300ustar00rootroot00000000000000###################################################################################### # Fakenect Mock Library ###################################################################################### SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/fakenect) add_library (fakenect SHARED fakenect.c) set_target_properties ( fakenect PROPERTIES VERSION ${PROJECT_VER} SOVERSION ${PROJECT_APIVER} OUTPUT_NAME freenect) target_link_libraries(fakenect ${MATH_LIB}) install (TARGETS fakenect DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}/fakenect") add_executable(fakenect-record record.c) target_link_libraries(fakenect-record freenect ${MATH_LIB}) install (TARGETS fakenect-record DESTINATION bin) CONFIGURE_FILE("fakenect.sh.in" "fakenect.sh" IMMEDIATE @ONLY) install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fakenect.sh DESTINATION bin RENAME fakenect) install(FILES fakenect.1 fakenect-record.1 DESTINATION ${PROJECT_MANPAGE_INSTALL_DIR}/man1) libfreenect-0.5.3/fakenect/README000066400000000000000000000055011264163024100164410ustar00rootroot00000000000000Fakenect (c) 2010 Brandyn White See this blog post for more info http://brandynwhite.com/fakenect-openkinect-driver-simulator-experime Description This consists of a "record" program to save dumps from the kinect sensor and a library that can be linked to, providing an interface compatible with freenect. This allows you to save data and repeat for experiments, debug problems, share datasets, and experiment with the kinect without having one. Record ./record my_output // NOTE: output directory is created for you The program takes one argument (the output directory) and saves the acceleration, depth, and rgb data as individual files with names in the form "TYPE-CURRENTIME-TIMESTAMP" where TYPE is either (a)ccel, (d)epth, or (r)gb, TIMESTAMP corresponds to the timestamp associated with the observation (or in the case of accel, the last timestamp seen), and CURRENTTIME corresponds to a floating point version of the time in seconds. The purpose of storing the current time is so that delays can be recreated exactly as they occurred. For RGB and DEPTH the dump is just the entirety of the data provided in PPM and PGM formats respectively (just a 1 line header above the raw dump). For ACCEL, the dump is the 'freenect_raw_tilt_state'. Only the front part of the file name is used, with the rest left undefined (extension, extra info, etc). A file called INDEX.txt is also output with all of the filenames local to that directory to simplify the format (e.g., no need to read the directory structure). Here is an example of using the program mkdir out sudo ./record out And it will keep running, when you want to stop it, hit Ctrl-C and the signal will be caught, runloop stopped, and everything will be stored cleanly. Library Use the resulting fakenect .so dynamically instead of libfreenect. We read 1 update from the index per call, so this needs to be called in a loop like usual. If the index line is a Depth/RGB image the provided callback is called. If the index line is accelerometer data, then it is used to update our internal state. If you query for the accelerometer data you get the last sensor reading that we have. The time delays are compensated as best as we can to match those from the original data and current run conditions (e.g., if it takes longer to run this code then we wait less). Build This is built with the main cmake script. This gives you a build/lib/fakenect/libfreenect.so (note that it has the same name, but it is not the same) that you dynamically link in instead of libfreenect.so. Evaluation There is a demo in wrappers/python, see the README there Here is an example of calling the cython demo sudo LD_LIBRARY_PATH="../../../fakenect/" FAKENECT_PATH="thanksgiving0" python demo_cv_depth_show.py Note the FAKENECT_PATH, you pass in the path to a directory made with "record"libfreenect-0.5.3/fakenect/fakenect-record.1000066400000000000000000000035101264163024100206750ustar00rootroot00000000000000.TH FAKENECT-RECORD 1 2012-01-29 "libfreenect" "libfreenect manual" .SH NAME fakenect-record - program to save dumps from kinect to file .SH SYNOPSIS .SY fakenect-record .OP \-h .OP \-ffmpeg .OP \-ffmpeg-opts \fIoptions\fP .I outputdir .br .SH DESCRIPTION .LP \fBfakenect-record\fP dumps the output of the kinect in \fIoutputdir\fP folder. It saves the acceleration, depth, and rgb data as individual files with names in the form "TYPE-CURRENTIME-TIMESTAMP" where: .IP " *" 3 TYPE is either (a)ccel, (d)epth, or (r)gb .IP " *" 3 TIMESTAMP corresponds to the timestamp associated with the observation (or in the case of accel, the last timestamp seen) .IP " *" 3 CURRENTTIME corresponds to a floating point version of the time in seconds. .LP The purpose of storing the current time is so that delays can be recreated exactly as they occurred. For RGB and DEPTH the dump is just the entirety of the data provided in PPM and PGM formats respectively (just a 1 line header above the raw dump). For ACCEL, the dump is the "freenect_raw_tilt_state". Only the front part of the file name is used, with the rest left undefined (extension, extra info, etc). .LP A file called INDEX.txt is also output with all of the filenames local to that directory to simplify the format (e.g., no need to read the directory structure). .LP Once started, the program will continue to acquire data from the kinect. When you want to stop it, hit Ctrl-C and the signal will be caught, runloop stopped, and everything will be stored cleanly. .SH OPTIONS .TP .B \-ffmpeg If present, send the the video stream to ffmpeg . .TP .B \-ffmpeg-opts \fIoptions\fP When using ffmpeg, specify the options to be used with it. If unspecified, it will use the options "\-aspect 4:3 \-r 20 \-vcodec msmpeg4 \-b 30000k" . .TP .B \-h Display the command-line help .SH "SEE ALSO" .BR fakenect (1) libfreenect-0.5.3/fakenect/fakenect.1000066400000000000000000000006631264163024100174270ustar00rootroot00000000000000.TH FAKENECT 1 2012-01-29 "libfreenect" "libfreenect manual" .SH NAME fakenect - Run a program by faking the Kinect .SH SYNOPSIS .SY fakenect .I database .I application .I args .br .SH DESCRIPTION .LP \fBfakenect\fP runs \fIapplication\fP with the arguments \fIargs\fP using the data contained in the folder \fIdatabase\fP. These data should have been recorded using \fIfakenect-record\fP(1). .SH "SEE ALSO" .BR fakenect-record (1) libfreenect-0.5.3/fakenect/fakenect.c000066400000000000000000000272441264163024100175150ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com) * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "platform.h" #include #include #include #include #include #include #define GRAVITY 9.80665 // The dev and ctx are just faked with these numbers static freenect_device *fake_dev = (freenect_device *)1234; static freenect_context *fake_ctx = (freenect_context *)5678; static freenect_depth_cb cur_depth_cb = NULL; static freenect_video_cb cur_rgb_cb = NULL; static char *input_path = NULL; static FILE *index_fp = NULL; static freenect_raw_tilt_state state = { 0 }; static int already_warned = 0; static double playback_prev_time = 0.; static double record_prev_time = 0.; static void *depth_buffer = NULL; static void *rgb_buffer = NULL; static int depth_running = 0; static int rgb_running = 0; static void *user_ptr = NULL; static char *one_line(FILE *fp) { int c; int pos = 0; char *out = NULL; for (c = fgetc(fp); !(c == '\n' || c == EOF); c = fgetc(fp)) { out = realloc(out, pos + 1); out[pos++] = c; } if (out) { out = realloc(out, pos + 1); out[pos] = '\0'; } return out; } static int get_data_size(FILE *fp) { int orig = ftell(fp); fseek(fp, 0L, SEEK_END); int out = ftell(fp); fseek(fp, orig, SEEK_SET); return out; } static int parse_line(char *type, double *cur_time, unsigned int *timestamp, unsigned int *data_size, char **data) { char *line = one_line(index_fp); if (!line) { printf("Warning: No more lines in [%s]\n", input_path); return -1; } int file_path_size = strlen(input_path) + strlen(line) + 50; char *file_path = malloc(file_path_size); snprintf(file_path, file_path_size, "%s/%s", input_path, line); // Open file FILE *cur_fp = fopen(file_path, "rb"); if (!cur_fp) { printf("Error: Cannot open file [%s]\n", file_path); exit(1); } // Parse data from file name int ret = 0; *data_size = get_data_size(cur_fp); sscanf(line, "%c-%lf-%u-%*s", type, cur_time, timestamp); *data = malloc(*data_size); if (fread(*data, *data_size, 1, cur_fp) != 1) { printf("Error: Couldn't read entire file.\n"); ret = -1; } fclose(cur_fp); free(line); free(file_path); return ret; } static void open_index() { input_path = getenv("FAKENECT_PATH"); if (!input_path) { printf("Error: Environmental variable FAKENECT_PATH is not set. Set it to a path that was created using the 'record' utility.\n"); exit(1); } int index_path_size = strlen(input_path) + 50; char *index_path = malloc(index_path_size); snprintf(index_path, index_path_size, "%s/INDEX.txt", input_path); index_fp = fopen(index_path, "rb"); if (!index_fp) { printf("Error: Cannot open file [%s]\n", index_path); exit(1); } free(index_path); } static char *skip_line(char *str) { char *out = strchr(str, '\n'); if (!out) { printf("Error: PGM/PPM has incorrect formatting, expected a header on one line followed by a newline\n"); exit(1); } return out + 1; } int freenect_process_events(freenect_context *ctx) { /* This is where the magic happens. We read 1 update from the index per call, so this needs to be called in a loop like usual. If the index line is a Depth/RGB image the provided callback is called. If the index line is accelerometer data, then it is used to update our internal state. If you query for the accelerometer data you get the last sensor reading that we have. The time delays are compensated as best as we can to match those from the original data and current run conditions (e.g., if it takes longer to run this code then we wait less). */ if (!index_fp) open_index(); char type; double record_cur_time; unsigned int timestamp, data_size; char *data = NULL; if (parse_line(&type, &record_cur_time, ×tamp, &data_size, &data)) return -1; // Sleep an amount that compensates for the original and current delays // playback_ is w.r.t. the current time // record_ is w.r.t. the original time period during the recording if (record_prev_time != 0. && playback_prev_time != 0.) sleep_highres((record_cur_time - record_prev_time) - (get_time() - playback_prev_time)); record_prev_time = record_cur_time; switch (type) { case 'd': if (cur_depth_cb && depth_running) { void *cur_depth = skip_line(data); if (depth_buffer) { memcpy(depth_buffer, cur_depth, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT).bytes); cur_depth = depth_buffer; } cur_depth_cb(fake_dev, cur_depth, timestamp); } break; case 'r': if (cur_rgb_cb && rgb_running) { void *cur_rgb = skip_line(data); if (rgb_buffer) { memcpy(rgb_buffer, cur_rgb, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes); cur_rgb = rgb_buffer; } cur_rgb_cb(fake_dev, cur_rgb, timestamp); } break; case 'a': if (data_size == sizeof(state)) { memcpy(&state, data, sizeof(state)); } else if (!already_warned) { already_warned = 1; printf("\n\nWarning: Accelerometer data has an unexpected" " size [%u] instead of [%u]. The acceleration " "and tilt data will be substituted for dummy " "values. This data was probably made with an " "older version of record (the upstream interface " "changed).\n\n", data_size, (unsigned int)sizeof state); } break; } free(data); playback_prev_time = get_time(); return 0; } int freenect_process_events_timeout(freenect_context *ctx, struct timeval *timeout) { return freenect_process_events(ctx); } double freenect_get_tilt_degs(freenect_raw_tilt_state *state) { // NOTE: This is duped from tilt.c, this is the only function we need from there return ((double)state->tilt_angle) / 2.; } freenect_raw_tilt_state* freenect_get_tilt_state(freenect_device *dev) { return &state; } freenect_tilt_status_code freenect_get_tilt_status(freenect_raw_tilt_state *state) { return state->tilt_status; } void freenect_get_mks_accel(freenect_raw_tilt_state *state, double* x, double* y, double* z) { //the documentation for the accelerometer (http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf) //states there are 819 counts/g *x = (double)state->accelerometer_x/FREENECT_COUNTS_PER_G*GRAVITY; *y = (double)state->accelerometer_y/FREENECT_COUNTS_PER_G*GRAVITY; *z = (double)state->accelerometer_z/FREENECT_COUNTS_PER_G*GRAVITY; } void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb) { cur_depth_cb = cb; } void freenect_set_video_callback(freenect_device *dev, freenect_video_cb cb) { cur_rgb_cb = cb; } int freenect_set_video_mode(freenect_device* dev, const freenect_frame_mode mode) { // Always say it was successful but continue to pass through the // underlying data. Would be better to check for conflict. return 0; } int freenect_set_depth_mode(freenect_device* dev, const freenect_frame_mode mode) { // Always say it was successful but continue to pass through the // underlying data. Would be better to check for conflict. return 0; } freenect_frame_mode freenect_find_video_mode(freenect_resolution res, freenect_video_format fmt) { assert(FREENECT_RESOLUTION_MEDIUM == res); assert(FREENECT_VIDEO_RGB == fmt); // NOTE: This will leave uninitialized values if new fields are added. // To update this line run the "record" program, look at the top output freenect_frame_mode out = {256, 1, {0}, 921600, 640, 480, 24, 0, 30, 1}; return out; } int freenect_get_video_mode_count() { return 1; } freenect_frame_mode freenect_get_video_mode(int mode_num) { return freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB); } freenect_frame_mode freenect_get_current_video_mode(freenect_device *dev) { return freenect_get_video_mode(0); } freenect_frame_mode freenect_find_depth_mode(freenect_resolution res, freenect_depth_format fmt) { assert(FREENECT_RESOLUTION_MEDIUM == res); assert(FREENECT_DEPTH_11BIT == fmt); // NOTE: This will leave uninitialized values if new fields are added. // To update this line run the "record" program, look at the top output freenect_frame_mode out = {256, 1, {0}, 614400, 640, 480, 11, 5, 30, 1}; return out; } int freenect_get_depth_mode_count() { return 1; } freenect_frame_mode freenect_get_depth_mode(int mode_num) { return freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT); } freenect_frame_mode freenect_get_current_depth_mode(freenect_device *dev) { return freenect_get_depth_mode(0); } int freenect_num_devices(freenect_context *ctx) { // Always 1 device return 1; } int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index) { // Set it to some number to allow for NULL checks *dev = fake_dev; return 0; } int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char* camera_serial) { *dev = fake_dev; return 0; } int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx) { *ctx = fake_ctx; return 0; } int freenect_supported_subdevices(void) { return FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA; } void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs) { // Ideally, we'd actually check for MOTOR and CAMERA and AUDIO, but for now // we just ignore them and provide all captured data. } int freenect_set_depth_buffer(freenect_device *dev, void *buf) { depth_buffer = buf; return 0; } int freenect_set_video_buffer(freenect_device *dev, void *buf) { rgb_buffer = buf; return 0; } void freenect_set_user(freenect_device *dev, void *user) { user_ptr = user; } void *freenect_get_user(freenect_device *dev) { return user_ptr; } int freenect_start_depth(freenect_device *dev) { depth_running = 1; return 0; } int freenect_start_video(freenect_device *dev) { rgb_running = 1; return 0; } int freenect_stop_depth(freenect_device *dev) { depth_running = 0; return 0; } int freenect_stop_video(freenect_device *dev) { rgb_running = 0; return 0; } int freenect_set_video_format(freenect_device *dev, freenect_video_format fmt) { assert(fmt == FREENECT_VIDEO_RGB); return 0; } int freenect_set_depth_format(freenect_device *dev, freenect_depth_format fmt) { assert(fmt == FREENECT_DEPTH_11BIT); return 0; } void freenect_set_log_callback(freenect_context *ctx, freenect_log_cb cb) {} void freenect_set_log_level(freenect_context *ctx, freenect_loglevel level) {} int freenect_shutdown(freenect_context *ctx) { return 0; } int freenect_close_device(freenect_device *dev) { return 0; } int freenect_set_tilt_degs(freenect_device *dev, double angle) { return 0; } int freenect_set_led(freenect_device *dev, freenect_led_options option) { return 0; } int freenect_update_tilt_state(freenect_device *dev) { return 0; } libfreenect-0.5.3/fakenect/fakenect.sh.in000077500000000000000000000036031264163024100203060ustar00rootroot00000000000000#!/bin/bash # This file is part of the OpenKinect Project. http://www.openkinect.org # # Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file # for details. # # This code is licensed to you under the terms of the Apache License, version # 2.0, or, at your option, the terms of the GNU General Public License, # version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, # or the following URLs: # http://www.apache.org/licenses/LICENSE-2.0 # http://www.gnu.org/licenses/gpl-2.0.txt # # If you redistribute this file in source form, modified or unmodified, # you may: # 1) Leave this header intact and distribute it under the same terms, # accompanying it with the APACHE20 and GPL20 files, or # 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or # 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file # In all cases you must keep the copyright notice intact and include a copy # of the CONTRIB file. # Binary distributions must follow the binary distribution requirements of # either License. # fakenect wrapper script: # simplifies calling libfreenect applications under fakenect # by taking the fakenect database, app to run, and its args # then filling out the necessary environment variables and calling the app # usage: fakenect /path/to/fakenect/dump app --arg=value # catch bad args if [ $# -lt 2 ] then echo "Usage: $0 " exit -1 fi # set path to fakenect database export FAKENECT_PATH=$1 # set link path (LD_LIBRARY_PATH for Linux, DYLIB_LIBRARY_PATH for OS X) if [ `uname` == "Darwin" ]; then export DYLD_LIBRARY_PATH="@CMAKE_INSTALL_PREFIX@/@PROJECT_LIBRARY_INSTALL_DIR@/fakenect/:${DYLD_LIBRARY_PATH}" else export LD_LIBRARY_PATH="@CMAKE_INSTALL_PREFIX@/@PROJECT_LIBRARY_INSTALL_DIR@/fakenect/:${LD_LIBRARY_PATH}" fi # run desired app w/ args, now that environment is configured "${@:2}" libfreenect-0.5.3/fakenect/platform.h000066400000000000000000000041341264163024100175570ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com) * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include #ifdef _WIN32 #include #include #define snprintf _snprintf #define popen _popen #else #include #include #endif double get_time() { #ifdef _WIN32 SYSTEMTIME st; GetSystemTime(&st); FILETIME ft; SystemTimeToFileTime(&st, &ft); ULARGE_INTEGER li; li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; // FILETIME is given as a 64-bit value for the number of 100-nanosecond // intervals that have passed since Jan 1, 1601 (UTC). The difference between that // epoch and the POSIX epoch (Jan 1, 1970) is 116444736000000000 such ticks. uint64_t total_usecs = (li.QuadPart - 116444736000000000L) / 10L; return (total_usecs / 1000000.); #else struct timeval cur; gettimeofday(&cur, NULL); return cur.tv_sec + cur.tv_usec / 1000000.; #endif } void sleep_highres(double tm) { #ifdef _WIN32 int msec = floor(tm * 1000); if (msec > 0) { Sleep(msec); } #else int sec = floor(tm); int usec = (tm - sec) * 1000000; if (tm > 0) { sleep(sec); usleep(usec); } #endif } libfreenect-0.5.3/fakenect/record.c000066400000000000000000000222051264163024100172030ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com) * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "platform.h" #include #include #include #include #include #include char *out_dir=0; volatile sig_atomic_t running = 1; uint32_t last_timestamp = 0; FILE *index_fp = NULL; #define FREENECT_FRAME_W 640 #define FREENECT_FRAME_H 480 int use_ffmpeg = 0; char *ffmpeg_opts = 0; char *depth_name = 0; char *rgb_name = 0; FILE *depth_stream=0; FILE *rgb_stream=0; void dump_depth(FILE *fp, void *data, int data_size) { fprintf(fp, "P5 %d %d 65535\n", FREENECT_FRAME_W, FREENECT_FRAME_H); fwrite(data, data_size, 1, fp); } void dump_rgb(FILE *fp, void *data, int data_size) { fprintf(fp, "P6 %d %d 255\n", FREENECT_FRAME_W, FREENECT_FRAME_H); fwrite(data, data_size, 1, fp); } FILE *open_dump(char type, double cur_time, uint32_t timestamp, int data_size, const char *extension) { char *fn = malloc(strlen(out_dir) + 50); sprintf(fn, "%c-%f-%u.%s", type, cur_time, timestamp, extension); fprintf(index_fp, "%s\n", fn); sprintf(fn, "%s/%c-%f-%u.%s", out_dir, type, cur_time, timestamp, extension); FILE* fp = fopen(fn, "wb"); if (!fp) { printf("Error: Cannot open file [%s]\n", fn); exit(1); } printf("%s\n", fn); free(fn); return fp; } FILE *open_ffmpeg(char *output_filename) { char cmd[1024]; if (ffmpeg_opts==0) ffmpeg_opts = "-aspect 4:3 -r 20 -vcodec msmpeg4 -b 30000k"; snprintf(cmd, 1024, "ffmpeg -pix_fmt rgb24 -s %dx%d -f rawvideo " "-i /dev/stdin %s %s", FREENECT_FRAME_W, FREENECT_FRAME_H, ffmpeg_opts, output_filename); fprintf(stderr, "%s\n", cmd); FILE* proc = popen(cmd, "w"); if (!proc) { printf("Error: Cannot run ffmpeg\n"); exit(1); } return proc; } void dump(char type, uint32_t timestamp, void *data, int data_size) { // timestamp can be at most 10 characters, we have a few extra double cur_time = get_time(); FILE *fp; last_timestamp = timestamp; switch (type) { case 'd': fp = open_dump(type, cur_time, timestamp, data_size, "pgm"); dump_depth(fp, data, data_size); fclose(fp); break; case 'r': fp = open_dump(type, cur_time, timestamp, data_size, "ppm"); dump_rgb(fp, data, data_size); fclose(fp); break; case 'a': fp = open_dump(type, cur_time, timestamp, data_size, "dump"); fwrite(data, data_size, 1, fp); fclose(fp); break; } } void dump_ffmpeg_24(FILE *stream, uint32_t timestamp, void *data, int data_size) { fwrite(data, data_size, 1, stream); } void dump_ffmpeg_pad16(FILE *stream, uint32_t timestamp, void *data, int data_size) { unsigned int z = 0; uint16_t* data_ptr = (uint16_t*)data; uint16_t* end = data_ptr + data_size; while (data_ptr < end) { z = *data_ptr; fwrite(((char*)(&z)), 3, 1, stream); data_ptr += 2; } } void snapshot_accel(freenect_device *dev) { freenect_raw_tilt_state* state; if (!last_timestamp) return; freenect_update_tilt_state(dev); state = freenect_get_tilt_state(dev); dump('a', last_timestamp, state, sizeof *state); } void depth_cb(freenect_device *dev, void *depth, uint32_t timestamp) { dump('d', timestamp, depth, freenect_get_current_depth_mode(dev).bytes); } void rgb_cb(freenect_device *dev, void *rgb, uint32_t timestamp) { dump('r', timestamp, rgb, freenect_get_current_video_mode(dev).bytes); } void depth_cb_ffmpeg(freenect_device *dev, void *depth, uint32_t timestamp) { double cur_time = get_time(); fprintf(index_fp, "d-%f-%u\n", cur_time, timestamp); dump_ffmpeg_pad16(depth_stream, timestamp, depth, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT).bytes); } void rgb_cb_ffmpeg(freenect_device *dev, void *rgb, uint32_t timestamp) { double cur_time = get_time(); fprintf(index_fp, "d-%f-%u\n", cur_time, timestamp); dump_ffmpeg_24(rgb_stream, timestamp, rgb, freenect_get_current_video_mode(dev).bytes); } void init_ffmpeg_streams() { depth_stream = open_ffmpeg(depth_name); rgb_stream = open_ffmpeg(rgb_name); } void print_mode(const char *name, freenect_frame_mode mode) { /* This is just a courtesy function to let the user know the mode if it becomes a bother for maintainability just comment out the code in its body. It will only break if struct entries go missing. */ printf("%s Mode: {%d, %d, {%d}, %d, %d, %d, %d, %d, %d, %d}\n", name, mode.reserved, (int)mode.resolution, (int)mode.video_format, mode.bytes, mode.width, mode.height, mode.data_bits_per_pixel, mode.padding_bits_per_pixel, mode.framerate, mode.is_valid); } void init() { freenect_context *ctx; freenect_device *dev; if (freenect_init(&ctx, 0)) { printf("Error: Cannot get context\n"); return; } // fakenect doesn't support audio yet, so don't bother claiming the device freenect_select_subdevices(ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); if (freenect_open_device(ctx, &dev, 0)) { printf("Error: Cannot get device\n"); return; } print_mode("Depth", freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); print_mode("Video", freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); freenect_set_depth_mode(dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); freenect_start_depth(dev); freenect_set_video_mode(dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); freenect_start_video(dev); if (use_ffmpeg) { init_ffmpeg_streams(); freenect_set_depth_callback(dev, depth_cb_ffmpeg); freenect_set_video_callback(dev, rgb_cb_ffmpeg); } else { freenect_set_depth_callback(dev, depth_cb); freenect_set_video_callback(dev, rgb_cb); } while (running && freenect_process_events(ctx) >= 0) snapshot_accel(dev); freenect_stop_depth(dev); freenect_stop_video(dev); freenect_close_device(dev); freenect_shutdown(ctx); } FILE *open_index(const char *fn) { FILE *fp = fopen(fn, "r"); if (fp) { fclose(fp); printf("Error: Index already exists, to avoid overwriting " "use a different directory.\n"); return 0; } fp = fopen(fn, "wb"); if (!fp) { printf("Error: Cannot open file [%s]\n", fn); return 0; } return fp; } void signal_cleanup(int num) { running = 0; printf("Caught signal, cleaning up\n"); signal(SIGINT, signal_cleanup); } void usage() { printf("Records the Kinect sensor data to a directory\nResult can be used as input to Fakenect\nUsage:\n"); printf(" record [-h] [-ffmpeg] [-ffmpeg-opts ] " "\n"); exit(0); } int main(int argc, char **argv) { int c=1; while (c < argc) { if (strcmp(argv[c],"-ffmpeg")==0) use_ffmpeg = 1; else if (strcmp(argv[c],"-ffmpeg-opts")==0) { if (++c < argc) ffmpeg_opts = argv[c]; } else if (strcmp(argv[c],"-h")==0) usage(); else out_dir = argv[c]; c++; } if (!out_dir) usage(); signal(SIGINT, signal_cleanup); if (use_ffmpeg) { FILE *f; char *index_fn = malloc(strlen(out_dir) + 50); sprintf(index_fn, "%s-index.txt", out_dir); index_fp = open_index(index_fn); free(index_fn); if (!index_fp) return 1; depth_name = malloc(strlen(out_dir) + 50); rgb_name = malloc(strlen(out_dir) + 50); sprintf(depth_name, "%s-depth.avi", out_dir); sprintf(rgb_name, "%s-rgb.avi", out_dir); f = fopen(depth_name, "r"); if (f) { printf("Error: %s already exists, to avoid overwriting " "use a different name.\n", depth_name); fclose(f); exit(1); } f = fopen(rgb_name, "r"); if (f) { printf("Error: %s already exists, to avoid overwriting " "use a different name.\n", depth_name); fclose(f); exit(1); } init(); free(depth_name); free(rgb_name); if (depth_stream) fclose(depth_stream); if (rgb_stream) fclose(rgb_stream); fclose(index_fp); } else { #ifdef _WIN32 _mkdir(out_dir); #else mkdir(out_dir, S_IRWXU | S_IRWXG | S_IRWXO); #endif char *fn = malloc(strlen(out_dir) + 50); sprintf(fn, "%s/INDEX.txt", out_dir); index_fp = open_index(fn); free(fn); if (!index_fp) { fclose(index_fp); return 1; } init(); fclose(index_fp); } return 0; } libfreenect-0.5.3/include/000077500000000000000000000000001264163024100154235ustar00rootroot00000000000000libfreenect-0.5.3/include/libfreenect.h000066400000000000000000000657401264163024100200720ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include /* We need struct timeval */ #ifdef _WIN32 #include #else #include #endif #ifdef __cplusplus extern "C" { #endif #define FREENECT_COUNTS_PER_G 819 /**< Ticks per G for accelerometer as set per http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf */ /// Maximum value that a uint16_t pixel will take on in the buffer of any of the FREENECT_DEPTH_MM or FREENECT_DEPTH_REGISTERED frame callbacks #define FREENECT_DEPTH_MM_MAX_VALUE 10000 /// Value indicating that this pixel has no data, when using FREENECT_DEPTH_MM or FREENECT_DEPTH_REGISTERED depth modes #define FREENECT_DEPTH_MM_NO_VALUE 0 /// Maximum value that a uint16_t pixel will take on in the buffer of any of the FREENECT_DEPTH_11BIT, FREENECT_DEPTH_10BIT, FREENECT_DEPTH_11BIT_PACKED, or FREENECT_DEPTH_10BIT_PACKED frame callbacks #define FREENECT_DEPTH_RAW_MAX_VALUE 2048 /// Value indicating that this pixel has no data, when using FREENECT_DEPTH_11BIT, FREENECT_DEPTH_10BIT, FREENECT_DEPTH_11BIT_PACKED, or FREENECT_DEPTH_10BIT_PACKED #define FREENECT_DEPTH_RAW_NO_VALUE 2047 /// Flags representing devices to open when freenect_open_device() is called. /// In particular, this allows libfreenect to grab only a subset of the devices /// in the Kinect, so you could (for instance) use libfreenect to handle audio /// and motor support while letting OpenNI have access to the cameras. /// If a device is not supported on a particular platform, its flag will be ignored. typedef enum { FREENECT_DEVICE_MOTOR = 0x01, FREENECT_DEVICE_CAMERA = 0x02, FREENECT_DEVICE_AUDIO = 0x04, } freenect_device_flags; /// A struct used in enumeration to give access to serial numbers, so you can /// open a particular device by serial rather than depending on index. This /// is most useful if you have more than one Kinect. struct freenect_device_attributes { struct freenect_device_attributes *next; // Next device in the linked list const char* camera_serial; // Serial number of camera or audio subdevice }; /// Enumeration of available resolutions. /// Not all available resolutions are actually supported for all video formats. /// Frame modes may not perfectly match resolutions. For instance, /// FREENECT_RESOLUTION_MEDIUM is 640x488 for the IR camera. typedef enum { FREENECT_RESOLUTION_LOW = 0, /**< QVGA - 320x240 */ FREENECT_RESOLUTION_MEDIUM = 1, /**< VGA - 640x480 */ FREENECT_RESOLUTION_HIGH = 2, /**< SXGA - 1280x1024 */ FREENECT_RESOLUTION_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */ } freenect_resolution; /// Enumeration of video frame information states. /// See http://openkinect.org/wiki/Protocol_Documentation#RGB_Camera for more information. typedef enum { FREENECT_VIDEO_RGB = 0, /**< Decompressed RGB mode (demosaicing done by libfreenect) */ FREENECT_VIDEO_BAYER = 1, /**< Bayer compressed mode (raw information from camera) */ FREENECT_VIDEO_IR_8BIT = 2, /**< 8-bit IR mode */ FREENECT_VIDEO_IR_10BIT = 3, /**< 10-bit IR mode */ FREENECT_VIDEO_IR_10BIT_PACKED = 4, /**< 10-bit packed IR mode */ FREENECT_VIDEO_YUV_RGB = 5, /**< YUV RGB mode */ FREENECT_VIDEO_YUV_RAW = 6, /**< YUV Raw mode */ FREENECT_VIDEO_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */ } freenect_video_format; /// Enumeration of depth frame states /// See http://openkinect.org/wiki/Protocol_Documentation#RGB_Camera for more information. typedef enum { FREENECT_DEPTH_11BIT = 0, /**< 11 bit depth information in one uint16_t/pixel */ FREENECT_DEPTH_10BIT = 1, /**< 10 bit depth information in one uint16_t/pixel */ FREENECT_DEPTH_11BIT_PACKED = 2, /**< 11 bit packed depth information */ FREENECT_DEPTH_10BIT_PACKED = 3, /**< 10 bit packed depth information */ FREENECT_DEPTH_REGISTERED = 4, /**< processed depth data in mm, aligned to 640x480 RGB */ FREENECT_DEPTH_MM = 5, /**< depth to each pixel in mm, but left unaligned to RGB image */ FREENECT_DEPTH_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */ } freenect_depth_format; /// Enumeration of flags to toggle features with freenect_set_flag() typedef enum { // values written to the CMOS register FREENECT_AUTO_EXPOSURE = 1 << 14, FREENECT_AUTO_WHITE_BALANCE = 1 << 1, FREENECT_RAW_COLOR = 1 << 4, // arbitrary bitfields to support flag combination FREENECT_MIRROR_DEPTH = 1 << 16, FREENECT_MIRROR_VIDEO = 1 << 17, FREENECT_NEAR_MODE = 1 << 18, // K4W only } freenect_flag; /// Possible values for setting each `freenect_flag` typedef enum { FREENECT_OFF = 0, FREENECT_ON = 1, } freenect_flag_value; /// Structure to give information about the width, height, bitrate, /// framerate, and buffer size of a frame in a particular mode, as /// well as the total number of bytes needed to hold a single frame. typedef struct { uint32_t reserved; /**< unique ID used internally. The meaning of values may change without notice. Don't touch or depend on the contents of this field. We mean it. */ freenect_resolution resolution; /**< Resolution this freenect_frame_mode describes, should you want to find it again with freenect_find_*_frame_mode(). */ union { int32_t dummy; freenect_video_format video_format; freenect_depth_format depth_format; }; /**< The video or depth format that this freenect_frame_mode describes. The caller should know which of video_format or depth_format to use, since they called freenect_get_*_frame_mode() */ int32_t bytes; /**< Total buffer size in bytes to hold a single frame of data. Should be equivalent to width * height * (data_bits_per_pixel+padding_bits_per_pixel) / 8 */ int16_t width; /**< Width of the frame, in pixels */ int16_t height; /**< Height of the frame, in pixels */ int8_t data_bits_per_pixel; /**< Number of bits of information needed for each pixel */ int8_t padding_bits_per_pixel; /**< Number of bits of padding for alignment used for each pixel */ int8_t framerate; /**< Approximate expected frame rate, in Hz */ int8_t is_valid; /**< If 0, this freenect_frame_mode is invalid and does not describe a supported mode. Otherwise, the frame_mode is valid. */ } freenect_frame_mode; /// Enumeration of LED states /// See http://openkinect.org/wiki/Protocol_Documentation#Setting_LED for more information. typedef enum { LED_OFF = 0, /**< Turn LED off */ LED_GREEN = 1, /**< Turn LED to Green */ LED_RED = 2, /**< Turn LED to Red */ LED_YELLOW = 3, /**< Turn LED to Yellow */ LED_BLINK_GREEN = 4, /**< Make LED blink Green */ // 5 is same as 4, LED blink Green LED_BLINK_RED_YELLOW = 6, /**< Make LED blink Red/Yellow */ } freenect_led_options; /// Enumeration of tilt motor status typedef enum { TILT_STATUS_STOPPED = 0x00, /**< Tilt motor is stopped */ TILT_STATUS_LIMIT = 0x01, /**< Tilt motor has reached movement limit */ TILT_STATUS_MOVING = 0x04, /**< Tilt motor is currently moving to new position */ } freenect_tilt_status_code; /// Data from the tilt motor and accelerometer typedef struct { int16_t accelerometer_x; /**< Raw accelerometer data for X-axis, see FREENECT_COUNTS_PER_G for conversion */ int16_t accelerometer_y; /**< Raw accelerometer data for Y-axis, see FREENECT_COUNTS_PER_G for conversion */ int16_t accelerometer_z; /**< Raw accelerometer data for Z-axis, see FREENECT_COUNTS_PER_G for conversion */ int8_t tilt_angle; /**< Raw tilt motor angle encoder information */ freenect_tilt_status_code tilt_status; /**< State of the tilt motor (stopped, moving, etc...) */ } freenect_raw_tilt_state; struct _freenect_context; typedef struct _freenect_context freenect_context; /**< Holds information about the usb context. */ struct _freenect_device; typedef struct _freenect_device freenect_device; /**< Holds device information. */ // usb backend specific section typedef void freenect_usb_context; /**< Holds libusb-1.0 context */ // /// If Win32, export all functions for DLL usage #ifndef _WIN32 #define FREENECTAPI /**< DLLExport information for windows, set to nothing on other platforms */ #else /**< DLLExport information for windows, set to nothing on other platforms */ #ifdef __cplusplus #define FREENECTAPI extern "C" __declspec(dllexport) #else // this is required when building from a Win32 port of gcc without being // forced to compile all of the library files (.c) with g++... #define FREENECTAPI __declspec(dllexport) #endif #endif /// Enumeration of message logging levels typedef enum { FREENECT_LOG_FATAL = 0, /**< Log for crashing/non-recoverable errors */ FREENECT_LOG_ERROR, /**< Log for major errors */ FREENECT_LOG_WARNING, /**< Log for warning messages */ FREENECT_LOG_NOTICE, /**< Log for important messages */ FREENECT_LOG_INFO, /**< Log for normal messages */ FREENECT_LOG_DEBUG, /**< Log for useful development messages */ FREENECT_LOG_SPEW, /**< Log for slightly less useful messages */ FREENECT_LOG_FLOOD, /**< Log EVERYTHING. May slow performance. */ } freenect_loglevel; /** * Initialize a freenect context and do any setup required for * platform specific USB libraries. * * @param ctx Address of pointer to freenect context struct to allocate and initialize * @param usb_ctx USB context to initialize. Can be NULL if not using multiple contexts. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx); /** * Closes the device if it is open, and frees the context * * @param ctx freenect context to close/free * * @return 0 on success */ FREENECTAPI int freenect_shutdown(freenect_context *ctx); /// Typedef for logging callback functions typedef void (*freenect_log_cb)(freenect_context *dev, freenect_loglevel level, const char *msg); /** * Set the log level for the specified freenect context * * @param ctx context to set log level for * @param level log level to use (see freenect_loglevel enum) */ FREENECTAPI void freenect_set_log_level(freenect_context *ctx, freenect_loglevel level); /** * Callback for log messages (i.e. for rerouting to a file instead of * stdout) * * @param ctx context to set log callback for * @param cb callback function pointer */ FREENECTAPI void freenect_set_log_callback(freenect_context *ctx, freenect_log_cb cb); /** * Calls the platform specific usb event processor * * @param ctx context to process events for * * @return 0 on success, other values on error, platform/library dependant */ FREENECTAPI int freenect_process_events(freenect_context *ctx); /** * Calls the platform specific usb event processor until either an event occurs * or the timeout parameter time has passed. If a zero timeval is passed, this * function will handle any already-pending events, then return immediately. * * @param ctx Context to process events for * @param timeout Pointer to a timeval containing the maximum amount of time to block waiting for events, or zero for nonblocking mode * * @return 0 on success, other values on error, platform/library dependant */ FREENECTAPI int freenect_process_events_timeout(freenect_context *ctx, struct timeval* timeout); /** * Return the number of kinect devices currently connected to the * system * * @param ctx Context to access device count through * * @return Number of devices connected, < 0 on error */ FREENECTAPI int freenect_num_devices(freenect_context *ctx); /** * Scans for kinect devices and produces a linked list of their attributes * (namely, serial numbers), returning the number of devices. * * @param ctx Context to scan for kinect devices with * @param attribute_list Pointer to where this function will store the resultant linked list * * @return Number of devices connected, < 0 on error */ FREENECTAPI int freenect_list_device_attributes(freenect_context *ctx, struct freenect_device_attributes** attribute_list); /** * Free the linked list produced by freenect_list_device_attributes(). * * @param attribute_list Linked list of attributes to free. */ FREENECTAPI void freenect_free_device_attributes(struct freenect_device_attributes* attribute_list); /** * Answer which subdevices this library supports. This is most useful for * wrappers trying to determine whether the underlying library was built with * audio support or not, so the wrapper can avoid calling functions that do not * exist. * * @return Flags representing the subdevices that the library supports opening (see freenect_device_flags) */ FREENECTAPI int freenect_supported_subdevices(void); /** * Set which subdevices any subsequent calls to freenect_open_device() * should open. This will not affect devices which have already been * opened. The default behavior, should you choose not to call this * function at all, is to open all supported subdevices - motor, cameras, * and audio, if supported on the platform. * * @param ctx Context to set future subdevice selection for * @param subdevs Flags representing the subdevices to select */ FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs); /** * Returns the devices that are enabled after calls to freenect_open_device() * On newer kinects the motor and audio are automatically disabled for now * * @param ctx Context to set future subdevice selection for * @return Flags representing the subdevices that were actually opened (see freenect_device_flags) */ FREENECTAPI freenect_device_flags freenect_enabled_subdevices(freenect_context *ctx); /** * Opens a kinect device via a context. Index specifies the index of * the device on the current state of the bus. Bus resets may cause * indexes to shift. * * @param ctx Context to open device through * @param dev Device structure to assign opened device to * @param index Index of the device on the bus * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index); /** * Opens a kinect device (via a context) associated with a particular camera * subdevice serial number. This function will fail if no device with a * matching serial number is found. * * @param ctx Context to open device through * @param dev Device structure to assign opened device to * @param camera_serial Null-terminated ASCII string containing the serial number of the camera subdevice in the device to open * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char* camera_serial); /** * Closes a device that is currently open * * @param dev Device to close * * @return 0 on success */ FREENECTAPI int freenect_close_device(freenect_device *dev); /** * Set the device user data, for passing generic information into * callbacks * * @param dev Device to attach user data to * @param user User data to attach */ FREENECTAPI void freenect_set_user(freenect_device *dev, void *user); /** * Retrieve the pointer to user data from the device struct * * @param dev Device from which to get user data * * @return Pointer to user data */ FREENECTAPI void *freenect_get_user(freenect_device *dev); /// Typedef for depth image received event callbacks typedef void (*freenect_depth_cb)(freenect_device *dev, void *depth, uint32_t timestamp); /// Typedef for video image received event callbacks typedef void (*freenect_video_cb)(freenect_device *dev, void *video, uint32_t timestamp); /// Typedef for stream chunk processing callbacks typedef void (*freenect_chunk_cb)(void *buffer, void *pkt_data, int pkt_num, int datalen, void *user_data); /** * Set callback for depth information received event * * @param dev Device to set callback for * @param cb Function pointer for processing depth information */ FREENECTAPI void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb); /** * Set callback for video information received event * * @param dev Device to set callback for * @param cb Function pointer for processing video information */ FREENECTAPI void freenect_set_video_callback(freenect_device *dev, freenect_video_cb cb); /** * Set callback for depth chunk processing * * @param dev Device to set callback for * @param cb Function pointer for processing depth chunk */ FREENECTAPI void freenect_set_depth_chunk_callback(freenect_device *dev, freenect_chunk_cb cb); /** * Set callback for video chunk processing * * @param dev Device to set callback for * @param cb Function pointer for processing video chunk */ FREENECTAPI void freenect_set_video_chunk_callback(freenect_device *dev, freenect_chunk_cb cb); /** * Set the buffer to store depth information to. Size of buffer is * dependant on depth format. See FREENECT_DEPTH_*_SIZE defines for * more information. * * @param dev Device to set depth buffer for. * @param buf Buffer to store depth information to. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_set_depth_buffer(freenect_device *dev, void *buf); /** * Set the buffer to store depth information to. Size of buffer is * dependant on video format. See FREENECT_VIDEO_*_SIZE defines for * more information. * * @param dev Device to set video buffer for. * @param buf Buffer to store video information to. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_set_video_buffer(freenect_device *dev, void *buf); /** * Start the depth information stream for a device. * * @param dev Device to start depth information stream for. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_start_depth(freenect_device *dev); /** * Start the video information stream for a device. * * @param dev Device to start video information stream for. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_start_video(freenect_device *dev); /** * Stop the depth information stream for a device * * @param dev Device to stop depth information stream on. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_stop_depth(freenect_device *dev); /** * Stop the video information stream for a device * * @param dev Device to stop video information stream on. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_stop_video(freenect_device *dev); /** * Updates the accelerometer state using a blocking control message * call. * * @param dev Device to get accelerometer data from * * @return 0 on success, < 0 on error. Accelerometer data stored to * device struct. */ FREENECTAPI int freenect_update_tilt_state(freenect_device *dev); /** * Retrieve the tilt state from a device * * @param dev Device to retrieve tilt state from * * @return The tilt state struct of the device */ FREENECTAPI freenect_raw_tilt_state* freenect_get_tilt_state(freenect_device *dev); /** * Return the tilt state, in degrees with respect to the horizon * * @param state The tilt state struct from a device * * @return Current degree of tilt of the device */ FREENECTAPI double freenect_get_tilt_degs(freenect_raw_tilt_state *state); /** * Set the tilt state of the device, in degrees with respect to the * horizon. Uses blocking control message call to update * device. Function return does not reflect state of device, device * may still be moving to new position after the function returns. Use * freenect_get_tilt_status() to find current movement state. * * @param dev Device to set tilt state * @param angle Angle the device should tilt to * * @return 0 on success, < 0 on error. */ FREENECTAPI int freenect_set_tilt_degs(freenect_device *dev, double angle); /** * Return the movement state of the tilt motor (moving, stopped, etc...) * * @param state Raw state struct to get the tilt status code from * * @return Status code of the tilt device. See * freenect_tilt_status_code enum for more info. */ FREENECTAPI freenect_tilt_status_code freenect_get_tilt_status(freenect_raw_tilt_state *state); /** * Set the state of the LED. Uses blocking control message call to * update device. * * @param dev Device to set the LED state * @param option LED state to set on device. See freenect_led_options enum. * * @return 0 on success, < 0 on error */ FREENECTAPI int freenect_set_led(freenect_device *dev, freenect_led_options option); /** * Get the axis-based gravity adjusted accelerometer state, as laid * out via the accelerometer data sheet, which is available at * * http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf * * @param state State to extract accelerometer data from * @param x Stores X-axis accelerometer state * @param y Stores Y-axis accelerometer state * @param z Stores Z-axis accelerometer state */ FREENECTAPI void freenect_get_mks_accel(freenect_raw_tilt_state *state, double* x, double* y, double* z); /** * Get the number of video camera modes supported by the driver. This includes both RGB and IR modes. * * @return Number of video modes supported by the driver */ FREENECTAPI int freenect_get_video_mode_count(); /** * Get the frame descriptor of the nth supported video mode for the * video camera. * * @param mode_num Which of the supported modes to return information about * * @return A freenect_frame_mode describing the nth video mode */ FREENECTAPI freenect_frame_mode freenect_get_video_mode(int mode_num); /** * Get the frame descriptor of the current video mode for the specified * freenect device. * * @param dev Which device to return the currently-set video mode for * * @return A freenect_frame_mode describing the current video mode of the specified device */ FREENECTAPI freenect_frame_mode freenect_get_current_video_mode(freenect_device *dev); /** * Convenience function to return a mode descriptor matching the * specified resolution and video camera pixel format, if one exists. * * @param res Resolution desired * @param fmt Pixel format desired * * @return A freenect_frame_mode that matches the arguments specified, if such a valid mode exists; otherwise, an invalid freenect_frame_mode. */ FREENECTAPI freenect_frame_mode freenect_find_video_mode(freenect_resolution res, freenect_video_format fmt); /** * Sets the current video mode for the specified device. If the * freenect_frame_mode specified is not one provided by the driver * e.g. from freenect_get_video_mode() or freenect_find_video_mode() * then behavior is undefined. The current video mode cannot be * changed while streaming is active. * * @param dev Device for which to set the video mode * @param mode Frame mode to set * * @return 0 on success, < 0 if error */ FREENECTAPI int freenect_set_video_mode(freenect_device* dev, freenect_frame_mode mode); /** * Get the number of depth camera modes supported by the driver. This includes both RGB and IR modes. * * @return Number of depth modes supported by the driver */ FREENECTAPI int freenect_get_depth_mode_count(); /** * Get the frame descriptor of the nth supported depth mode for the * depth camera. * * @param mode_num Which of the supported modes to return information about * * @return A freenect_frame_mode describing the nth depth mode */ FREENECTAPI freenect_frame_mode freenect_get_depth_mode(int mode_num); /** * Get the frame descriptor of the current depth mode for the specified * freenect device. * * @param dev Which device to return the currently-set depth mode for * * @return A freenect_frame_mode describing the current depth mode of the specified device */ FREENECTAPI freenect_frame_mode freenect_get_current_depth_mode(freenect_device *dev); /** * Convenience function to return a mode descriptor matching the * specified resolution and depth camera pixel format, if one exists. * * @param res Resolution desired * @param fmt Pixel format desired * * @return A freenect_frame_mode that matches the arguments specified, if such a valid mode exists; otherwise, an invalid freenect_frame_mode. */ FREENECTAPI freenect_frame_mode freenect_find_depth_mode(freenect_resolution res, freenect_depth_format fmt); /** * Sets the current depth mode for the specified device. The mode * cannot be changed while streaming is active. * * @param dev Device for which to set the depth mode * @param mode Frame mode to set * * @return 0 on success, < 0 if error */ FREENECTAPI int freenect_set_depth_mode(freenect_device* dev, const freenect_frame_mode mode); /** * Enables or disables the specified flag. * * @param flag Feature to set * @param value `FREENECT_OFF` or `FREENECT_ON` * * @return 0 on success, < 0 if error */ FREENECTAPI int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value); /** * Returns the brightness of the IR sensor. * * @param dev Device to get IR brightness * * @return IR brightness value in the range 1 - 50, < 0 if error */ FREENECTAPI int freenect_get_ir_brightness(freenect_device *dev); /** * Sets the brightness of the IR sensor. * Note that this does not change the intensity of the IR projector. * * @param dev Device to set IR brightness * @param brighness Brightness value in range 1 - 50 * * @return 0 on success, < 0 if error */ FREENECTAPI int freenect_set_ir_brightness(freenect_device *dev, uint16_t brightness); /** * Allows the user to specify a pointer to the audio firmware in memory for the Xbox 360 Kinect * * @param ctx Context to open device through * @param fw_ptr Pointer to audio firmware loaded in memory * @param num_bytes The size of the firmware in bytes */ FREENECTAPI void freenect_set_fw_address_nui(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes); /** * Allows the user to specify a pointer to the audio firmware in memory for the K4W Kinect * * @param ctx Context to open device through * @param fw_ptr Pointer to audio firmware loaded in memory * @param num_bytes The size of the firmware in bytes */ FREENECTAPI void freenect_set_fw_address_k4w(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes); #ifdef __cplusplus } #endif libfreenect-0.5.3/include/libfreenect_audio.h000066400000000000000000000110621264163024100212370ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" #include #ifdef __cplusplus extern "C" { #endif /// Structure to represent a single 16-bit signed little-endian PCM sample. typedef struct { int16_t left; int16_t right; int16_t center; int16_t lfe; int16_t surround_left; int16_t surround_right; } freenect_sample_51; /** * Typedef for "you wanted this microphone data, here it is" event callbacks. * TODO: Timestamp details * The format of the unknown stream is as of yet undetermined. * * @param dev Device which triggered this callback * @param num_samples Number of samples provided in each of the audio data arrays (mic[1-4] and cancelled) * @param mic1 Microphone data for the leftmost microphone: 32-bit PCM little-endian samples at 16kHz. * @param mic2 Microphone data for the left-middle microphone: 32-bit PCM little-endian samples at 16kHz. * @param mic3 Microphone data for the right-middle microphone: 32-bit PCM little-endian samples at 16kHz. * @param mic4 Microphone data for the rightmost microphone: 32-bit PCM little-endian samples at 16kHz. * @param cancelled Noise-cancelled audio data: 16-bit PCM little-endian samples at 16kHz. */ typedef void (*freenect_audio_in_cb)(freenect_device *dev, int num_samples, int32_t* mic1, int32_t* mic2, int32_t* mic3, int32_t* mic4, int16_t* cancelled, void *unknown/*, timestamp_t timestamp*/); /** * Typedef for "you're playing audio, the library needs you to fill up the outgoing audio buffer" event callbacks * The library will request samples at a rate of 48000Hz. * * @param dev Device this callback was triggered for * @param samples Pointer to the memory where the library expects you to copy the next sample_count freenect_sample_51's to. * @param sample_count Bidirectional. in: maximum number of samples the driver wants (don't copy in more than this, you'll clobber memory). out: actual number of samples provided to the driver. */ typedef void (*freenect_audio_out_cb)(freenect_device *dev, freenect_sample_51* samples, int* sample_count); /** * Set the audio in callback. This is the function called when the library * has new microphone samples. It will be called approximately 62.5 times per * second (16kHz sample rate, expect 512 samples/callback) * * @param dev Device for which to set the callback * @param callback Callback function to set */ FREENECTAPI void freenect_set_audio_in_callback(freenect_device *dev, freenect_audio_in_cb callback); /** * Set the audio out callback. This is the "tell me what audio you're about * to play through the speakers so the Kinect can subtract it out" callback for * a given device. If you choose not set an audio_out_callback, the library * will send silence to the Kinect for you - it requires data either way. * * @param dev Device for which to set the callback * @param callback Callback function to set */ FREENECTAPI void freenect_set_audio_out_callback(freenect_device *dev, freenect_audio_out_cb callback); /** * Start streaming audio for the specified device. * * @param dev Device for which to start audio streaming * * @return 0 on success, < 0 if error */ FREENECTAPI int freenect_start_audio(freenect_device* dev); /** * Stop streaming audio for the specified device. * * @param dev Device for which to stop audio streaming * * @return 0 on success, < 0 if error */ FREENECTAPI int freenect_stop_audio(freenect_device* dev); #ifdef __cplusplus } #endif libfreenect-0.5.3/include/libfreenect_registration.h000066400000000000000000000074451264163024100226620ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" #include #ifdef __cplusplus extern "C" { #endif /// Internal Kinect registration parameters. /// Structure matches that of the line protocol /// of the Kinect. typedef struct { int32_t dx_center; // not used by mapping algorithm int32_t ax; int32_t bx; int32_t cx; int32_t dx; int32_t dx_start; int32_t ay; int32_t by; int32_t cy; int32_t dy; int32_t dy_start; int32_t dx_beta_start; int32_t dy_beta_start; int32_t rollout_blank; // not used by mapping algorithm int32_t rollout_size; // not used by mapping algorithm int32_t dx_beta_inc; int32_t dy_beta_inc; int32_t dxdx_start; int32_t dxdy_start; int32_t dydx_start; int32_t dydy_start; int32_t dxdxdx_start; int32_t dydxdx_start; int32_t dxdxdy_start; int32_t dydxdy_start; int32_t back_comp1; // not used by mapping algorithm int32_t dydydx_start; int32_t back_comp2; // not used by mapping algorithm int32_t dydydy_start; } freenect_reg_info; /// registration padding info (?) typedef struct { uint16_t start_lines; uint16_t end_lines; uint16_t cropping_lines; } freenect_reg_pad_info; /// internal Kinect zero plane data typedef struct { float dcmos_emitter_dist; // Distance between IR camera and IR emitter, in cm. float dcmos_rcmos_dist; // Distance between IR camera and RGB camera, in cm. float reference_distance; // The focal length of the IR camera, in mm. float reference_pixel_size; // The size of a single pixel on the zero plane, in mm. } freenect_zero_plane_info; /// all data needed for depth->RGB mapping typedef struct { freenect_reg_info reg_info; freenect_reg_pad_info reg_pad_info; freenect_zero_plane_info zero_plane_info; double const_shift; uint16_t* raw_to_mm_shift; int32_t* depth_to_rgb_shift; int32_t (*registration_table)[2]; // A table of 640*480 pairs of x,y values. // Index first by pixel, then x:0 and y:1. } freenect_registration; // These allow clients to export registration parameters; proper docs will // come later FREENECTAPI freenect_registration freenect_copy_registration(freenect_device* dev); FREENECTAPI int freenect_destroy_registration(freenect_registration* reg); // convenience function to convert a single x-y coordinate pair from camera // to world coordinates FREENECTAPI void freenect_camera_to_world(freenect_device* dev, int cx, int cy, int wz, double* wx, double* wy); // helper function to map one FREENECT_VIDEO_RGB image to a FREENECT_DEPTH_MM // image (inverse mapping to FREENECT_DEPTH_REGISTERED, which is depth -> RGB) FREENECTAPI void freenect_map_rgb_to_depth( freenect_device* dev, uint16_t* depth_mm, uint8_t* rgb_raw, uint8_t* rgb_registered ); #ifdef __cplusplus } #endif libfreenect-0.5.3/libfreenectConfig.cmake.in000066400000000000000000000006111264163024100210150ustar00rootroot00000000000000get_filename_component(CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) set(FREENECT_INCLUDE_DIRS "${CONFIG_DIR}/../../@PROJECT_INCLUDE_INSTALL_DIR@") set(FREENECT_RUNTIME_LIBRARY_DIRS "${CONFIG_DIR}/../../bin") set(FREENECT_LIBRARY_DIRS "${CONFIG_DIR}/../../@PROJECT_LIBRARY_INSTALL_DIR@") #/libfreenect.so.@PROJECT_VER@ set(FREENECT_LIBRARIES "freenect") set(FREENECT_VERSION "@PROJECT_VER@") libfreenect-0.5.3/mkcontrib.sh000066400000000000000000000005761264163024100163340ustar00rootroot00000000000000#!/bin/sh echo "The following people have contributed to libfreenect:" > CONTRIB echo >> CONTRIB # note: some exclusions to clean up botched git author tags that got fixed in # later commits, hopefully we'll be more careful about this in the future git log --format='%aN <%aE>' | sort | uniq | grep -E -v \ 'brandyn@router|sl203|mwise@bvo|richmattes|kai.*none' | sort >> CONTRIB libfreenect-0.5.3/platform/000077500000000000000000000000001264163024100156245ustar00rootroot00000000000000libfreenect-0.5.3/platform/linux/000077500000000000000000000000001264163024100167635ustar00rootroot00000000000000libfreenect-0.5.3/platform/linux/portage/000077500000000000000000000000001264163024100204245ustar00rootroot00000000000000libfreenect-0.5.3/platform/linux/portage/dev-libs/000077500000000000000000000000001264163024100221315ustar00rootroot00000000000000libfreenect-0.5.3/platform/linux/portage/dev-libs/libfreenect/000077500000000000000000000000001264163024100244135ustar00rootroot00000000000000libfreenect-0.5.3/platform/linux/portage/dev-libs/libfreenect/Manifest000066400000000000000000000005771264163024100261150ustar00rootroot00000000000000EBUILD libfreenect-9999.ebuild 2052 SHA256 cc490bd4f5c593d6cbee2c3e878389b85930893402c284f6d5c181ba5664f2e0 SHA512 a62f206923766eb6f468edbebff6109cdd77b1a7a4a80d8c0825d93ae9b7f881a3f15ec7fac0d4916b995150820ca1a7ac6ed1a625a47289632db3f95720be8d WHIRLPOOL 197fec2ca649a664fd02cdde6d704962e51d4970907cbf1092171646612bf5e34a6eae0784b23dc608b3c4438cecd261a8cd78528d695c18bb53fc7c0577d642 libfreenect-0.5.3/platform/linux/portage/dev-libs/libfreenect/libfreenect-9999.ebuild000066400000000000000000000040041264163024100305020ustar00rootroot00000000000000# Copyright 1999-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ EAPI="5" inherit cmake-utils git-2 multilib python DESCRIPTION="Core library for accessing the Microsoft Kinect." HOMEPAGE="https://github.com/OpenKinect/${PN}" EGIT_REPO_URI="git://github.com/OpenKinect/${PN}.git" LICENSE="Apache-2.0 GPL-2" SLOT="0" KEYWORDS="" IUSE="bindist +c_sync +cpp doc examples fakenect opencv openni2 python" PYTHON_DEPEND="!bindist? 2" COMMON_DEP="virtual/libusb:1 examples? ( media-libs/freeglut virtual/opengl x11-libs/libXi x11-libs/libXmu ) opencv? ( media-libs/opencv ) python? ( dev-python/numpy )" RDEPEND="${COMMON_DEP}" DEPEND="${COMMON_DEP} dev-util/cmake virtual/pkgconfig doc? ( app-doc/doxygen ) python? ( dev-python/cython )" src_configure() { local mycmakeargs=( $(cmake-utils_use_build bindist REDIST_PACKAGE) $(cmake-utils_use_build c_sync C_SYNC) $(cmake-utils_use_build cpp CPP) $(cmake-utils_use_build examples EXAMPLES) $(cmake-utils_use_build fakenect FAKENECT) $(cmake-utils_use_build opencv CV) $(cmake-utils_use_build openni2 OPENNI2_DRIVER) $(cmake-utils_use_build python PYTHON) ) cmake-utils_src_configure } src_install() { cmake-utils_src_install # udev rules insinto /lib/udev/rules.d/ doins "${S}"/platform/linux/udev/51-kinect.rules # documentation dodoc README.md if use doc; then cd doc doxygen || ewarn "doxygen failed" dodoc -r html || ewarn "dodoc failed" cd - fi } pkg_postinst() { if ! use bindist; then ewarn "The bindist USE flag is disabled. Resulting binaries may not be legal to re-distribute." fi elog "Make sure your user is in the 'video' group" elog "Just run 'gpasswd -a video', then have re-login." } libfreenect-0.5.3/platform/linux/udev/000077500000000000000000000000001264163024100177265ustar00rootroot00000000000000libfreenect-0.5.3/platform/linux/udev/51-kinect.rules000066400000000000000000000011271264163024100225030ustar00rootroot00000000000000# ATTR{product}=="Xbox NUI Motor" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02b0", MODE="0666" # ATTR{product}=="Xbox NUI Audio" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02ad", MODE="0666" # ATTR{product}=="Xbox NUI Camera" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02ae", MODE="0666" # Kinect for Windows SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02c2", MODE="0666" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02be", MODE="0666" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02bf", MODE="0666" libfreenect-0.5.3/platform/linux/udev/README000066400000000000000000000001401264163024100206010ustar00rootroot00000000000000Simply place this file in /etc/udev/rules.d and you'll no longer need to run your apps as root. libfreenect-0.5.3/platform/windows/000077500000000000000000000000001264163024100173165ustar00rootroot00000000000000libfreenect-0.5.3/platform/windows/README.TXT000066400000000000000000000430601264163024100206570ustar00rootroot00000000000000====================================================================================== SUMMARY ******* 1) libfreenect: incompatibilities with Visual C++ This section is here merely for historical reasons. All of the issues documented here were already fixed in the libfreenect repository and CMake should be able to produce a project that is ready to build libfreenect in Windows with Visual Studio. Consider browsing this section if experiencing compilation issues under different platforms, compilers and/or IDEs. 2) libusb-1.0 vs. libusbemu: Issues and Concept The current port of libfreenect for Windows uses a libusb-1.0 emulation layer since a proper port of libusb-1.0 for Windows is not yet available. Such emulation layer allows Windows development to keep in sync with the official development branch of libfreenect, without the need of dedicated drivers/implementations. This section discusses why and how the current libfreenect Windows port moved in this direction. 3) libusbemu: Tips, Hints and Best Practices The current status of libusbemu is quite reliable under normal usage circumstances, but by no means stable: caution is advised. This section provides some guidelines to avoid potential pitfalls and keep the application running safely under Windows. They are simple and natural to follow, so they should not impose any special design considerations for the application. 4) Overall performance of libfreenect in Windows The current Windows port of libfreenect has some performance overhead over other platforms and dedicated Win32 driver implementations due to the libusbemu module. This section contains a benchmark scenario and a also a discussion on the results. In short, the overhead is negligible and should not prevent anyone from using it. ====================================================================================== 1) libfreenect source code: incompatibilities with Visual C++ ********************************************************** ---------------------------------------------------------------------------------- Language issues: The Microsoft C compiler does not implement all the C99 standard. ---------------------------------------------------------------------------------- An attempt to compile the current libfreenect with Visual C++ will trigger a lot of errors. A simple workaround is to tell Visual Studio to force compilation all the ".c" files within the project using the C++ compiler: Project >> Properties >> C/C++ >> Advanced >> Compile As: Compile as C++ Code (/TP) This will get rid of most errors, except those regarding implicit pointer casts. Here are a few examples of such implicit pointer casts from within libfreenect: tilt.c dev->raw_state.tilt_status = buf[9]; core.c *ctx = malloc(sizeof(freenect_context)); cameras.c strm->raw_buf = strm->proc_buf; It seems that it is not possible to force Visual C++ to perform such implicit casts (if anyone knows how, please share! :-) Such implicit casts then have to be made explicit: dev->raw_state.tilt_status = (freenect_tilt_status_code)buf[9]; *ctx = (freenect_context*)malloc(sizeof(freenect_context)); strm->raw_buf = (uint8_t*)strm->proc_buf; Fortunately, they are not many, and it can be done in a couple of minutes. This should impose a minimal burden to the Win32 repository maintainers. NOTE: Sometimes, even when "Compile as C++ Code" is specified, the build will insist on using the C-compiler to compile .c files (this happens with MSVC versions prior to 2010). To work around this, just set the "Compile As" to "Default", click "Apply" and then set it back to "Compile as C++ Code (/TP)", click "Apply" and then "OK". Another problem is that Visual C++ does not offer . However, it can be emulated by #include and defining the "ssize_t" type. The implementation of is located at: "libfreenect\platform\windows\unistd.h" NOTE: MSVC versions prior to 2010 do not provide the header. An ISO C9x compilant header for such MSVC versions can be found at the wikipedia entry of stdint.h (at the "External links" section of the page): http://en.wikipedia.org/wiki/Stdint.h or directly through this link: http://msinttypes.googlecode.com/svn/trunk/stdint.h A copy of such header will be also provided within libfreenect in the future. The "freenect_internal.h" makes use of GCC's "__attribute__" keyword, and there is no such a thing in Visual C++. Fortunately, this header is not exposed for the library user and is just required during the library build. There are a few simple solutions for this issue: a) remove this keyword or b) define a dummy macro for it. Another issue is that since all .c files were forced to be compiled as C++ code, the "libfreenect.h" header no longer requires the "#ifdef __cpluscplus extern C" idiom. Commenting out this guard will do the trick, but better checking is possible. ----------------------------------------------------------------------------------- Library issues: libfreenect uses libusb-1.0 which is not yet available for Windows. ----------------------------------------------------------------------------------- The final issue is regarding the default USB back-end used by libfreenect, libusb-1.0, which is not yet available for Windows. This restriction forces the Windows port of libfreenect to implement its own back-end, which then splits the Windows port from the main development branch of libfreenect as new device features are reverse-engineered and added to the library. Fortunately, such restriction can be alleviated through the libusb-1.0 API "emulator" and keep the Windows port in sync with the current status of libfreenect. More on this subject in the following section. ====================================================================================== 2) libusb-1.0 vs. libusbemu: Issues and Concept ******************************************** The libfreenect uses libusb-1.0 as its default USB back-end to communicate with Kinect but libusb-1.0 is not yet available for Windows. The current libusb-1.0 implementation for Windows is experimental and uses WinUSB as its USB back-end. Unfortunately, WinUSB does not support isochronous transfers, rendering it useless for Kinect purposes. However, all is not lost since the latest version of libusb-win32 has support for the isochronous transfers imposed by Kinect. There are issues too: libusb-win32 is based on the old libusb-0.1 API which is incompatible with the libusb-1.0 API. Some of the initial efforts to port libfreenect to Windows were based on the libusb-win32, being Zephod's Win32 Kinect driver prototype a well-known instance: http://ajaxorg.posterous.com/kinect-driver-for-windows-prototype The problem with a dedicated libusb-win32 driver implementation is that it has to be maintained separately from the current libfreenect development. As new Kinect features are reverse-engineered and implemented in the official libfreenect branch, the Windows port requires additional maintenance to keep it in sync with the newest updates, even when such updates don't involve USB communication at all. One could argue that libfreenect should abandon the use of libusb-1.0 and just adopt the old libusb-0.1 instead, since it is has support in a wider range of platforms... This is out of question! First of all, libusb-0.1 still exists for legacy reasons, and it is highly recommended to move to the new API if possible. Moreover, libusb-0.1 does not have built-in support for asynchronous transfers, which would force libfreenect to hold and manage threads internally, which would then lead to a whole set of new issues that are prone to hurt performance, maintainability and portability. Fortunately, libfreenect only requires a small portion of the libusb-1.0 API, and such subset can be emulated, at some extent, through what is provided from libusb-win32. As a result, the burden of maintaining dedicated development branches for a Windows port is eliminated and the port can keep in synch with updates made in the libfreenect. One may now ask: how can libusb-win32 be of any help if it is based on the libusb-0.1 API, which has no support for asynchronous transfers? Well, that's because it happens that libusb-win32 is more than just a Win32 build of libusb-0.1: it is a special branch of the 0.1 API that extends it to allow asynchronous transfers. The normal execution flow of libfreenect is something like this: Application <-> libfreenect <-> libusb-1.0 <-> Kinect In Windows, the flow is as follows: Application <-> libfreenect <-> libusb-1.0-emu <-> libusb-win32 <-> Kinect The source code of the emulation layer is available at: libfreenect\platform\windows\libusb10emu\libusb-1.0 Keep in mind that libusb-win32 is still required, and can be downloaded from: http://sourceforge.net/apps/trac/libusb-win32/wiki The latest snapshots are recommended, obtained directly from this URL: http://sourceforge.net/projects/libusb-win32/files/libusb-win32-snapshots Emulation of libusb-1.0 on top of libusb-win32 is not trivial, in special because of some Windows-specific issues. There will be performance overhead, but as discussed in the "Overall Performance" section, this should not hurt the application performance at significant levels. Moreover, although the libusbemu is currently quite reliable, it is by no means stable and on par to the real libusb-1.0 semantics. Caution is advised, so be sure to read the following section for some usage considerations. The libusbemu sits completely hidden behind libfreenect: the application does not need to worry or call any special functions. In fact the application is not even aware that libusbemu exists. ====================================================================================== 3) libusbemu: Tips, Hints and Best Practices ***************************************** --------------------------------------------------------------- TIP: Trigger the Fail Guard if the system becomes unresponsive. --------------------------------------------------------------- Since libusbemu is quite experimental, there is a fail guard within it. If for some reason your system renders unresponsive, try focusing any window of the application and hold [CTRL] + [ALT] for a while. This will trigger a special synchronization event within the libusbemu which will interrupt the execution of any internal thread of libusbemu and prompt a message box to the user asking for action. You can either resume execution (if you unintentionally pressed [CTRL] + [ALT] in the console window) or abort libusbemu. The fail guard will never trigger if there is no incoming video or depth streams. The Fail Guard is important since in such situations one would most likely be forced to shutdown the computer (in a not so graceful way, by holding the power button!). ---------------------------------------- TIP: Only use a single freenect context. ---------------------------------------- Multiple freenect contexts should be no problem in the future. Having more than one device attached to the same context should work fine, but no tests were made so far. ----------------------------------------------------- TIP: Yield the rendering thread after each iteration. ----------------------------------------------------- In case your application performs direct rendering (OpenGL, Direct3D), it is highly recommended to yield the rendering thread after finishing rendering each frame. This can alleviate a lot of CPU usage. The ideal place for this yield is right after the swap-buffers call (SwapBuffers(), glutSwapBuffers(), Present(), etc). The best way to yield is by calling Sleep(1). Note that Sleep(0) is also possible, but the former is more "democratic". Note that some graphics drivers or platforms may already yield after swap-buffers. This seems to be the case with OpenGL NVIDIA drivers for Linux. In Windows, however, the same driver (version) does not yield. Maybe in Linux the "yielder" is not the driver itself, but the underlying implementation of glXSwapBuffers()... Anyway, when in doubt, it will not hurt to explicitly yield again. -------------------------------------------------------------------------------------- TIP: Perform stream operations only in the thread that calls freenect_process_events() -------------------------------------------------------------------------------------- By stream operations I mean these: freenect_start_video() freenect_start_depth() freenect_stop_video() freenect_stop_depth() This tip seems to hold for other platforms as well, and it is respected through all of the official libfreenect examples and should be of no burden for the application. This may be due to the underlying semantics of the real libusb-1.0. Unfortunately, although libusb-1.0 has an excellent API documentation it lacks on a proper specification, thus difficulting the task of checking if this is indeed a restriction. In summary, a typical libfreenect application (check the official examples) will have a dedicated thread that calls freenect_process_events(). This function is responsible for querying and dispatching incoming streams (a.k.a. video and depth frames) from the Kinect device to the application (behind the scenes is a call the libusb-1.0 function libusb_handle_events()) and it is advised that any stream operation intended by the application (like switching to some different video format) should happen within the thread that calls the freenect_process_events(). The official libfreenect examples do this, so be sure to check their source code if confused. It is also advised to have only one thread calling freenect_handle_events(). Interestingly, some tests were made with both the libusb-1.0 and libusbemu and mixing stream operations in different threads seem to work well. However, no guarantees are given if executed in such a fashion. Again, libusb-1.0 has no specification document and if such behavior is really to be expected is a hard task to determine. ====================================================================================== 4) Overall performance of libfreenect in Windows ********************************************* --------------------------------------------- THIS SECTION IS OUTDATED, GOTTA REDO IT SOON! --------------------------------------------- Hardware: * Notebook * CPU: Intel Core2 Duo 32bit [T7250] @ 2.0GHz * RAM: 4GB RAM * GPU: GeForce 8600M GT 256MB VRAM Task: display of simultaneous RGB (Bayer-to-RGB) and depth streams (16bit unpadded) on the screen through OpenGL textures. Application source code is identical for all tests (except for the Zephod's version that required some interface adaptation). Results: performance measurements refer to the average frame time (one loop iteration). Linux: Ubuntu Notebook 10.10 -- gcc 4.4.5 * Debug: 1.22ms | CPU @ 77% | video @ 30Hz | depth @ 30Hz * Release: 1.15ms | CPU @ 72% | video @ 30Hz | depth @ 30Hz Win32: Windows 7 Enterprise 32bit -- VC++ (Professional) 2010 1) libfreenect with libusbemu: * Debug: 2.44ms | CPU @ 75% | video @ 30Hz | depth @ 30Hz * Release: 1.93ms | CPU @ 63% | video @ 30Hz | depth @ 30Hz 2) Zephod's dedicated driver (V16): * Debug: 2.87ms | CPU @ 82% | video @ 30Hz | depth @ 30Hz * Release: 2.55ms | CPU @ 77% | video @ 30Hz | depth @ 30Hz Remarks: Debug builds account for the library itself being built in Debug mode (libfreenect or Zaphod's driver, whichever applies). Release builds also imply that the program was started without any debug information embedded. In Windows, time was measured through the Win32 exclusive QueryPerformanceFrequency() and QueryPerformanceCounter() routines. In Linux, the measurement was performed via POSIX gettime() function. A Win32 MinGW-based (gcc/g++ 4.5.0) build of libfreenect with libusbemu using POSIX gettime() also yielded to nearly identical performance results than VC++ 2010 with Performance Counters. All of the Win32 performance results were also double-checked with Fraps. In Windows, a single thread yield call was placed after rendering each screen frame (as recommended in Item 3-3). In Linux, the graphics driver - possibly glXSwapBuffers itself - seems to be already yielding the rendering thread, and forcing it in the code did not incur into any extra impact on performance. Discussion: Even though there are no streaming frequency discrepancies between platforms, one may infer, just from the frame times, that Windows clearly has an overhead disadvantage. However, this does not hold true: there is still plenty of time for the application logic to run. For a steady 60FPS (~16.66ms per frame) real-time performance, a Release build using libusbemu in Windows would still have about 14.70ms per frame available for the client code, while in Linux the available time would be around 15.50ms, a 0.8ms overhead between the platforms. Such a small difference should not impose any special design considerations for the client code. Furthermore, note that the CPU usage in Windows tend to be lower than in Linux. The reason behind this difference is quite difficult to summarize here, but it is probably related to the way Windows and Linux perform asynchronous I/O in USB-mapped files. The interested reader is encouraged to refer to the following links: > http://www.unwesen.de/articles/waitformultipleobjects_considered_expensive > http://softwarecommunity.intel.com/articles/eng/2807.htm > http://software.intel.com/en-us/blogs/2006/10/19/why-windows-threads-are-better-than-posix-threads/ The memory consumption overhead of libusbemu in Windows is negligible, and as far as the VC++ memory leak detection goes, libusbemu has no memory leaks. ====================================================================================== libfreenect-0.5.3/platform/windows/libusb10emu/000077500000000000000000000000001264163024100214465ustar00rootroot00000000000000libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/000077500000000000000000000000001264163024100232225ustar00rootroot00000000000000libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/failguard.cpp000066400000000000000000000032401264163024100256630ustar00rootroot00000000000000#include "failguard.h" #include "libusbemu_threads.h" int ThreadFailGuardProc(void* params); namespace libusbemu { namespace failguard { static volatile bool boTriggered (false); static QuickEvent hReaction; static volatile int nDecision (0); const bool Check() { if (failguard::boTriggered) return(true); // CTRL + ALT pressed? if ((GetKeyState(VK_CONTROL) & 0x8000) && (GetKeyState(VK_MENU) & 0x8000)) { // only one thread is allowed to activate the guard static QuickMutex mutexFailGuard; if (mutexFailGuard.TryEnter()) { if (!failguard::boTriggered) { failguard::hReaction.Reset(); failguard::boTriggered = true; new QuickThread(ThreadFailGuardProc, NULL, true); } mutexFailGuard.Leave(); } } return(failguard::boTriggered); } void WaitDecision() { failguard::hReaction.Wait(); } const bool Abort() { return(-1 == nDecision); } } } using namespace libusbemu::failguard; int ThreadFailGuardProc(void* params) { int user_option = MessageBoxA(GetDesktopWindow(), "The libusb_handle_events() fail guard of libusbemu was reached!\n" "This was caused by pressing and holding the [CTRL] + [ALT] keys.\n" "If it was unintentional, click Cancel to resume normal execution;\n" "otherwise, click OK to effectively terminate the thread (note that\n" "the host program might run abnormally after such termination).", "WARNING: libusbemu thread fail guard reached!", MB_ICONWARNING | MB_OKCANCEL); if (IDOK == user_option) nDecision = -1; else boTriggered = false; hReaction.Signal(); return(0); } libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/failguard.h000066400000000000000000000002171264163024100253310ustar00rootroot00000000000000#pragma once namespace libusbemu { namespace failguard { const bool Check(); void WaitDecision(); const bool Abort(); } } libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/libusb.h000066400000000000000000000153301264163024100246550ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once // This interface emulator requires the libusb-win32 v1.2.2.1 (snapshot) // or later. Prior win32 versions of the library were not conformal to // the official libusb-0.1 API naming convention // (e.g.: usb_device_t instead of usb_device) // One can either workaround prior releases to match the official naming // or upgrade to the libusb-win32 1.2.2.1 snapshot. #include #if defined(_MSC_VER) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; // We need struct timeval. #include #else #include #include #endif #define LIBUSBEMU 1 // guard to enable mix of compiler semantics (C/C++ calling C++); // this should allow builds under VC++ and gcc/g++ profiles #ifdef __cplusplus extern "C" { #endif // gotta use "_t" suffix here... struct libusb_context_t; // ...otherwise C++ complains with such typedef declaration typedef struct libusb_context_t libusb_context; int libusb_init(libusb_context** context); void libusb_exit(libusb_context* ctx); void libusb_set_debug(libusb_context *ctx, int level); struct libusb_device_t; typedef struct libusb_device_t libusb_device; ssize_t libusb_get_device_list(libusb_context* ctx, libusb_device*** list); void libusb_free_device_list(libusb_device** list, int unref_devices); int libusb_get_device_descriptor(libusb_device* dev, struct libusb_device_descriptor* desc); struct libusb_device_handle_t; typedef struct libusb_device_handle_t libusb_device_handle; int libusb_open(libusb_device* dev, libusb_device_handle** handle); void libusb_close(libusb_device_handle* dev_handle); int libusb_get_string_descriptor(libusb_device_handle *dev_handle, uint8_t desc_index, uint16_t langid, unsigned char *data, int length); int libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length); int libusb_set_configuration(libusb_device_handle *dev, int configuration); int libusb_set_interface_alt_setting(libusb_device_handle *dev,int interface_number,int alternate_setting); int libusb_claim_interface(libusb_device_handle* dev, int interface_number); int libusb_release_interface(libusb_device_handle* dev, int interface_number); libusb_device_handle *libusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); int libusb_control_transfer(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 libusb_bulk_transfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout); struct libusb_transfer* libusb_alloc_transfer(int iso_packets); void libusb_free_transfer(struct libusb_transfer* transfer); typedef void(*libusb_transfer_cb_fn)(struct libusb_transfer *transfer); void libusb_fill_iso_transfer(struct libusb_transfer* transfer, libusb_device_handle* dev_handle, unsigned char endpoint, unsigned char* buffer, int length, int num_iso_packets, libusb_transfer_cb_fn callback, void* user_data, unsigned int timeout); void libusb_set_iso_packet_lengths(struct libusb_transfer* transfer, unsigned int length); int libusb_submit_transfer(struct libusb_transfer* transfer); int libusb_cancel_transfer(struct libusb_transfer* transfer); int libusb_handle_events(libusb_context* ctx); // WORK IN PROGRESS... int libusb_handle_events_timeout(libusb_context* ctx, struct timeval* timeout); // the signature of libusb_device_descriptor is identical to usb_device_descriptor // which means that the below struct could be replaced by a typedef; however, that // would require #including in this header, polluting the scope and possibly // creating conflicts with existing declarations... struct libusb_device_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; uint8_t bDeviceClass; uint8_t bDeviceSubClass; uint8_t bDeviceProtocol; uint8_t bMaxPacketSize0; uint16_t idVendor; uint16_t idProduct; uint16_t bcdDevice; uint8_t iManufacturer; uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; }; enum libusb_endpoint_direction { LIBUSB_ENDPOINT_IN = 0x80, LIBUSB_ENDPOINT_OUT = 0x00 }; enum libusb_transfer_status { LIBUSB_TRANSFER_COMPLETED, LIBUSB_TRANSFER_ERROR, LIBUSB_TRANSFER_TIMED_OUT, LIBUSB_TRANSFER_CANCELLED, LIBUSB_TRANSFER_STALL, LIBUSB_TRANSFER_NO_DEVICE, LIBUSB_TRANSFER_OVERFLOW }; enum libusb_transfer_type { LIBUSB_TRANSFER_TYPE_CONTROL = 0, LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, LIBUSB_TRANSFER_TYPE_BULK = 2, LIBUSB_TRANSFER_TYPE_INTERRUPT = 3, }; enum libusb_transfer_flags { LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, }; struct libusb_transfer { libusb_device_handle *dev_handle; uint8_t flags; unsigned char endpoint; unsigned char type; unsigned int timeout; enum libusb_transfer_status status; int length; int actual_length; libusb_transfer_cb_fn callback; void *user_data; unsigned char *buffer; int num_iso_packets; struct libusb_iso_packet_descriptor* iso_packet_desc; }; struct libusb_iso_packet_descriptor { unsigned int length; unsigned int actual_length; enum libusb_transfer_status status; }; enum libusb_error { LIBUSB_SUCCESS = 0, LIBUSB_ERROR_IO = -1, LIBUSB_ERROR_INVALID_PARAM = -2, LIBUSB_ERROR_ACCESS = -3, LIBUSB_ERROR_NO_DEVICE = -4, LIBUSB_ERROR_NOT_FOUND = -5, LIBUSB_ERROR_BUSY = -6, LIBUSB_ERROR_TIMEOUT = -7, LIBUSB_ERROR_OVERFLOW = -8, LIBUSB_ERROR_PIPE = -9, LIBUSB_ERROR_INTERRUPTED = -10, LIBUSB_ERROR_NO_MEM = -11, LIBUSB_ERROR_NOT_SUPPORTED = -12, LIBUSB_ERROR_OTHER = -99, }; #ifdef __cplusplus } #endif libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp000066400000000000000000001056351264163024100257270ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ // Headers required to enable Visual C++ Memory Leak mechanism: // (NOTE: this should only be activated in Debug mode!) #if defined(_MSC_VER) && defined(_DEBUG) // MSVC version predefined macros: // http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/17a84d56-4713-48e4-a36d-763f4dba0c1c/ // _MSC_VER | MSVC Edition // ---------+--------------- // 1300 | MSVC .NET 2002 // 1310 | MSVC .NET 2003 // 1400 | MSVC 2005 // 1500 | MSVC 2008 // 1600 | MSVC 2010 // until VC71 (MSVC2003) the human-readable map/dump mode flag is CRTDBG_MAP_ALLOC: // http://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.71).aspx // but from VC80 (MSVC2005) and on the flag should be prefixed by a "_": // http://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.80).aspx #if _MSC_VER >= 1400 #define _CRTDBG_MAP_ALLOC #else #define CRTDBG_MAP_ALLOC #endif #include #include // Also, gotta redefine the new operator ... // http://support.microsoft.com/kb/140858 // but before redefining it, for MSVC version prior to 2010, the STL // header must be included in order to avoid some scary compilation issues: // http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/a6a148ed-aff1-4ec0-95d2-a82cd4c29cbb #if _MSC_VER < 1600 #include #endif // now it is safe to redefine the new operator #define LIBUSBEMU_DEBUG_NEW new ( _NORMAL_BLOCK, __FILE__, __LINE__) #define new LIBUSBEMU_DEBUG_NEW #endif #include "libusb.h" #include "libusbemu_internal.h" #include "failguard.h" #include #include #include "freenect_internal.h" using namespace libusbemu; #ifdef _DEBUG #define LIBUSBEMU_DEBUG_BUILD #endif//_DEBUG #ifdef LIBUSBEMU_DEBUG_BUILD #define LIBUSB_DEBUG_CMD(cmd) cmd #else #define LIBUSB_DEBUG_CMD(cmd) #endif//LIBUSBEMU_DEBUG_BUILD static libusb_context *default_context = NULL; int libusb_init(libusb_context** context) { usb_init(); LIBUSB_DEBUG_CMD ( const usb_version* version = usb_get_version(); fprintf(stdout, "libusb-win32: dll version %d.%d.%d.%d | driver (libusb0.sys) version %d.%d.%d.%d\n", version->dll.major, version->dll.minor, version->dll.micro, version->dll.nano, version->driver.major, version->driver.minor, version->driver.micro, version->driver.nano); ); // there is no such a thing like 'context' in libusb-0.1... // however, it is wise to emulate such context structure to localize and // keep track of any resource and/or internal data structures, as well as // to be able to clean-up itself at libusb_exit() if (context == NULL) context = &default_context; *context = new libusb_context; // 0 on success; LIBUSB_ERROR on failure return(0); } void libusb_exit(libusb_context* ctx) { if (ctx == NULL) ctx = default_context; ctx->mutex.Enter(); // before deleting the context, delete all devices/transfers still in there: while (!ctx->devices.empty()) { libusb_context::TMapDevices::iterator itDevice (ctx->devices.begin()); libusb_device& device (itDevice->second); if (NULL != device.handles) { // a simple "while(!device.handles->empty())" loop is impossible here // because after a call to libusb_close() the device may be already // destroyed (that's the official libusb-1.0 semantics when the ref // count reaches zero), rendering "device.handles" to a corrupt state. // an accurate "for" loop on the number of handles is the way to go. const int handles = device.handles->size(); for (int h=0; hbegin(); libusb_device_handle* handle (&(itHandle->second)); libusb_close(handle); } } } ctx->mutex.Leave(); delete(ctx); } void libusb_set_debug(libusb_context *ctx, int level) { // Note: libusb-win32 doesn't support context-specific loglevels, so this // sets the loglevel globally. If this is actually an issue for you, I // will be surprised. usb_set_debug(level); return; } ssize_t libusb_get_device_list(libusb_context* ctx, libusb_device*** list) { if (ctx == NULL) ctx = default_context; // libusb_device*** list demystified: // libusb_device*** is the C equivalent to libusb_device**& in C++; such declaration // allows the scope of this function libusb_get_device_list() to write on a variable // of type libusb_device** declared within the function scope of the caller. // libusb_device** is better understood as libusb_device*[], which is an array of // pointers of type libusb_device*, each pointing to a struct that holds actual data. usb_find_busses(); usb_find_devices(); usb_bus* bus = usb_get_busses(); while (bus) { struct usb_device* device = bus->devices; while (device) { libusbemu_register_device(ctx, device); device = device->next; }; bus = bus->next; }; // populate the device list that will be returned to the client: // the list must be NULL-terminated to follow the semantics of libusb-1.0! RAIIMutex lock (ctx->mutex); libusb_device**& devlist = *list; devlist = new libusb_device* [ctx->devices.size()+1]; // +1 is for a finalization mark libusb_context::TMapDevices::iterator it (ctx->devices.begin()); libusb_context::TMapDevices::iterator end (ctx->devices.end()); for (int i=0; it!=end; ++it, ++i) devlist[i] = &it->second; // finalization mark to assist later calls to libusb_free_device_list() devlist[ctx->devices.size()] = NULL; // the number of devices in the outputted list, or LIBUSB_ERROR_NO_MEM on memory allocation failure. return(ctx->devices.size()); } void libusb_free_device_list(libusb_device** list, int unref_devices) { if (NULL == list) return; if (unref_devices) { int i (0); while (list[i] != NULL) { libusbemu_unregister_device(list[i]); ++i; } } delete[](list); } int libusb_get_device_descriptor(libusb_device* dev, struct libusb_device_descriptor* desc) { struct usb_device* device (dev->device); usb_device_descriptor& device_desc (device->descriptor); // plain copy of one descriptor on to another: this is a safe operation because // usb_device_descriptor and libusb_device_descriptor have the same signature memcpy(desc, &device_desc, sizeof(libusb_device_descriptor)); // 0 on success; LIBUSB_ERROR on failure return(0); } int libusb_open(libusb_device* dev, libusb_device_handle** handle) { RAIIMutex lock (dev->ctx->mutex); usb_dev_handle* usb_handle (usb_open(dev->device)); if (NULL == usb_handle) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } if (NULL == dev->handles) dev->handles = new libusb_device::TMapHandles; libusb_device_handle_t dummy = { dev, usb_handle }; libusb_device::TMapHandles::iterator it = dev->handles->insert(std::make_pair(usb_handle,dummy)).first; *handle = &(it->second); assert((*handle)->dev == dev); assert((*handle)->handle == usb_handle); dev->refcount++; if (NULL == dev->isoTransfers) dev->isoTransfers = new libusb_device::TMapIsocTransfers; //0 on success // LIBUSB_ERROR_NO_MEM on memory allocation failure // LIBUSB_ERROR_ACCESS if the user has insufficient permissions // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // another LIBUSB_ERROR code on other failure return(0); } void libusb_close(libusb_device_handle* dev_handle) { RAIIMutex lock (dev_handle->dev->ctx->mutex); libusb_device* device (dev_handle->dev); if (device->handles->find(dev_handle->handle) == device->handles->end()) { LIBUSBEMU_ERROR("libusb_close() attempted to close an unregistered handle!\n"); return; } if (0 != usb_close(dev_handle->handle)) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return; } device->handles->erase(dev_handle->handle); libusbemu_unregister_device(device); } int libusb_get_string_descriptor(libusb_device_handle *dev_handle, uint8_t desc_index, uint16_t langid, unsigned char *data, int length) { RAIIMutex lock (dev_handle->dev->ctx->mutex); int bytes = usb_get_string(dev_handle->handle, (int)desc_index, (int)langid, (char*)data, (size_t)length); if (bytes < 0) { LIBUSBEMU_ERROR_LIBUSBWIN32(); } return bytes; } int libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length) { RAIIMutex lock (dev_handle->dev->ctx->mutex); int bytes = usb_get_string_simple(dev_handle->handle, (int)desc_index, (char*)data, (size_t)length); if (bytes < 0) { LIBUSBEMU_ERROR_LIBUSBWIN32(); } return bytes; } int libusb_set_configuration(libusb_device_handle *dev, int configuration) { RAIIMutex lock (dev->dev->ctx->mutex); int ret = usb_set_configuration(dev->handle, configuration); if (0 != ret) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return ret; } // returns: // 0 on success // LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist // LIBUSB_ERROR_BUSY if interfaces are currently claimed // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // another LIBUSB_ERROR code on other failure // return 0; } int libusb_set_interface_alt_setting(libusb_device_handle *dev, int interface_number,int alternate_setting){ RAIIMutex lock (dev->dev->ctx->mutex); if (0 != usb_set_altinterface(dev->handle, alternate_setting)) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } return(0); } int libusb_claim_interface(libusb_device_handle* dev, int interface_number) { RAIIMutex lock (dev->dev->ctx->mutex); // according to the official libusb-win32 usb_set_configuration() documentation: // http://sourceforge.net/apps/trac/libusb-win32/wiki/libusbwin32_documentation // "Must be called!: usb_set_configuration() must be called with a valid // configuration (not 0) before you can claim the interface. This might // not be be necessary in the future. This behavior is different from // Linux libusb-0.1." if (0 != usb_set_configuration(dev->handle, 1)) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } if (0 != usb_claim_interface(dev->handle, interface_number)) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } //if (0 != usb_set_altinterface(dev->handle, 0)) // return(LIBUSB_ERROR_OTHER); // LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist // LIBUSB_ERROR_BUSY if another program or driver has claimed the interface // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // a LIBUSB_ERROR code on other failure // 0 on success return(0); } int libusb_release_interface(libusb_device_handle* dev, int interface_number) { RAIIMutex lock (dev->dev->ctx->mutex); if (0 != usb_release_interface(dev->handle, interface_number)) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } // LIBUSB_ERROR_NOT_FOUND if the interface was not claimed // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // another LIBUSB_ERROR code on other failure // 0 on success return(0); } libusb_device_handle *libusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, uint16_t product_id) { int num_devices; libusb_device** list; libusb_device_handle *dev_handle = NULL; if (ctx == NULL) ctx = default_context; num_devices = libusb_get_device_list(ctx, &list); if (num_devices < 0) return NULL; unsigned int i = 0; while (list[i] != NULL) { struct libusb_device_descriptor desc; int ret = libusb_get_device_descriptor(list[i], &desc); if (ret < 0) break; if (desc.idVendor == vendor_id && desc.idProduct == product_id) { ret = libusb_open(list[i], &dev_handle); if (ret) break; } i++; } libusb_free_device_list(list, 1); return dev_handle; } int libusb_control_transfer(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) { // in libusb-1.0 a timeout of zero it means 'wait indefinitely'; in libusb-0.1, a timeout of zero means 'return immediatelly'! timeout = (0 == timeout) ? 60000 : timeout; // wait 60000ms (60s = 1min) if the transfer is supposed to wait indefinitely... int bytes_transferred = usb_control_msg(dev_handle->handle, bmRequestType, bRequest, wValue, wIndex, (char*)data, wLength, timeout); if (bytes_transferred < 0) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } // on success, the number of bytes actually transferred // LIBUSB_ERROR_TIMEOUT if the transfer timed out // LIBUSB_ERROR_PIPE if the control request was not supported by the device // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // another LIBUSB_ERROR code on other failures return(bytes_transferred); } int libusb_bulk_transfer(libusb_device_handle* dev_handle, uint8_t endpoint, uint8_t *data, int length, int *transferred, unsigned int timeout) { // in libusb-1.0 a timeout of zero it means 'wait indefinitely'; in libusb-0.1, a timeout of zero means 'return immediately'! timeout = (0 == timeout) ? 60000 : timeout; // wait 60000ms (60s = 1min) if the transfer is supposed to wait indefinitely... int bytes_transferred; if (endpoint & LIBUSB_ENDPOINT_IN) { // Device to Host bytes_transferred = usb_bulk_read(dev_handle->handle, endpoint, (char*)data, length, timeout); } else { // Host to Device bytes_transferred = usb_bulk_write(dev_handle->handle, endpoint, (char*)data, length, timeout); } if (bytes_transferred < 0) { // 0 on success (and populates transferred) // LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates transferred) // LIBUSB_ERROR_PIPE if the endpoint halted // LIBUSB_ERROR_OVERFLOW if the device offered more data, see Packets and overflows // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // another LIBUSB_ERROR code on other failures *transferred = 0; LIBUSBEMU_ERROR_LIBUSBWIN32(); return(LIBUSB_ERROR_OTHER); } *transferred = bytes_transferred; return 0; } // FROM HERE ON CODE BECOMES QUITE MESSY: ASYNCHRONOUS TRANSFERS MANAGEMENT struct libusb_transfer* libusb_alloc_transfer(int iso_packets) { transfer_wrapper* wrapper = new transfer_wrapper; memset(wrapper, 0, sizeof(transfer_wrapper)); libusb_transfer& transfer (wrapper->libusb); transfer.num_iso_packets = iso_packets; transfer.iso_packet_desc = new libusb_iso_packet_descriptor [iso_packets]; memset(transfer.iso_packet_desc, 0, iso_packets*sizeof(libusb_iso_packet_descriptor)); // a newly allocated transfer, or NULL on error return(&transfer); } void libusb_free_transfer(struct libusb_transfer* transfer) { // according to the official libusb_free_transfer() documentation: // "It is legal to call this function with a NULL transfer. // In this case, the function will simply return safely." if (NULL == transfer) return; // according to the official libusb_free_transfer() documentation: // "It is not legal to free an active transfer // (one which has been submitted and has not yet completed)." // that means that only "orphan" transfers can be deleted: transfer_wrapper* wrapper = libusbemu_get_transfer_wrapper(transfer); if (!libusb_device::TListTransfers::Orphan(wrapper)) { LIBUSBEMU_ERROR("libusb_free_transfer() attempted to free an active transfer!"); return; } if (0 != usb_free_async(&wrapper->usb)) { LIBUSBEMU_ERROR_LIBUSBWIN32(); return; } if (NULL != transfer->iso_packet_desc) delete[](transfer->iso_packet_desc); // according to the official libusb_free_transfer() documentation: // "If the LIBUSB_TRANSFER_FREE_BUFFER flag is set and the transfer buffer // is non-NULL, this function will also free the transfer buffer using the // standard system memory allocator (e.g. free())." if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) free(transfer->buffer); delete(wrapper); } void libusb_fill_iso_transfer(struct libusb_transfer* transfer, libusb_device_handle* dev_handle, unsigned char endpoint, unsigned char* buffer, int length, int num_iso_packets, libusb_transfer_cb_fn callback, void* user_data, unsigned int timeout) { // according to the official libusb_fill_iso_transfer() documentation: // "libusb_fill_iso_transfer() is a helper function to populate the required // libusb_transfer fields for an isochronous transfer." // What this means is that the library client is not required to call this // helper function in order to setup the fields within the libusb_transfer // struct. Thus, this is NOT the place for any sort of special processing // because there are no guarantees that such function will ever be invoked. transfer->dev_handle = dev_handle; transfer->endpoint = endpoint; transfer->buffer = buffer; transfer->length = length; transfer->num_iso_packets = num_iso_packets; transfer->callback = callback; transfer->timeout = timeout; transfer->user_data = user_data; transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; // control some additonal library duties such as: // LIBUSB_TRANSFER_SHORT_NOT_OK, LIBUSB_TRANSFER_FREE_BUFFER, LIBUSB_TRANSFER_FREE_TRANSFER transfer->flags; // these two are output parameters coming from actual transfers... transfer->actual_length; transfer->status; } void libusb_set_iso_packet_lengths(struct libusb_transfer* transfer, unsigned int length) { // according to the official libusb_fill_iso_transfer() documentation: // "Convenience function to set the length of all packets in an isochronous // transfer, based on the num_iso_packets field in the transfer structure." // For the same reasons as in libusb_fill_iso_transfer(), no additional // processing should ever happen withing this function... for (int i=0; i < transfer->num_iso_packets; ++i) transfer->iso_packet_desc[i].length = length; } int ReapThreadProc(void* params); int libusb_submit_transfer(struct libusb_transfer* transfer) { transfer_wrapper* wrapper = libusbemu_get_transfer_wrapper(transfer); // the first time a transfer is submitted, the libusb-0.1 transfer context // (the void*) must be created and initialized with a proper call to one of // the usb_***_setup_async() functions; one could thing of doing this setup // within libusb_fill_***_transfer(), but the latter are just convenience // functions to fill the transfer data structure: the library client is not // forced to call them and could fill the fields directly within the struct. if (NULL == wrapper->usb) libusbemu_setup_transfer(wrapper); libusbemu_clear_transfer(wrapper); int ret = usb_submit_async(wrapper->usb, (char*)transfer->buffer, transfer->length); if (ret < 0) { // TODO: better error handling... // what does usb_submit_async() actually returns on error? // LIBUSB_ERROR_NO_DEVICE if the device has been disconnected // LIBUSB_ERROR_BUSY if the transfer has already been submitted. // another LIBUSB_ERROR code on other failure LIBUSBEMU_ERROR_LIBUSBWIN32(); return(ret); } libusb_device::TMapIsocTransfers& isoTransfers (*transfer->dev_handle->dev->isoTransfers); libusb_device::TMapIsocTransfers::iterator it = isoTransfers.find(transfer->endpoint); if (isoTransfers.end() == it) { libusb_device::isoc_handle dummy = { libusb_device::TListTransfers(), NULL }; it = isoTransfers.insert(std::make_pair(transfer->endpoint, dummy)).first; } libusb_device::isoc_handle& iso (it->second); iso.listTransfers.Append(wrapper); if (NULL == iso.poReapThread) { void** state = new void* [2]; state[0] = transfer->dev_handle; state[1] = (void*)transfer->endpoint; iso.poReapThread = new QuickThread(ReapThreadProc, (void*)state, true); } // 0 on success return(0); } int libusb_cancel_transfer(struct libusb_transfer* transfer) { transfer_wrapper* wrapper = libusbemu_get_transfer_wrapper(transfer); // according to the official libusb_cancel_transfer() documentation: // "This function returns immediately, but this does not indicate // cancellation is complete. Your callback function will be invoked at // some later time with a transfer status of LIBUSB_TRANSFER_CANCELLED." // This semantic can be emulated by setting the transfer->status flag to // LIBUSB_TRANSFER_CANCELLED, leaving the rest to libusb_handle_events(). transfer->status = LIBUSB_TRANSFER_CANCELLED; int ret = usb_cancel_async(wrapper->usb); if (ret != 0) LIBUSBEMU_ERROR_LIBUSBWIN32(); // 0 on success // LIBUSB_ERROR_NOT_FOUND if the transfer is already complete or cancelled. // a LIBUSB_ERROR code on failure return(ret); } // FROM HERE ON CODE BECOMES REALLY REALLY REALLY MESSY: HANDLE EVENTS STUFF int libusbemu_handle_isochronous(libusb_context* ctx, const unsigned int milliseconds) { if (ctx == NULL) ctx = default_context; //QuickThread::Myself().RaisePriority(); RAIIMutex lock (ctx->mutDeliveryPool); int index = ctx->hWantToDeliverPool.WaitAnyUntilTimeout(milliseconds); if (-1 != index) { EventList hDoneDeliveringPoolLocal; while (-1 != (index = ctx->hWantToDeliverPool.CheckAny())) { ctx->hAllowDeliveryPool[index]->Signal(); ctx->hWantToDeliverPool[index]->Reset(); hDoneDeliveringPoolLocal.AttachEvent(ctx->hDoneDeliveringPool[index]); } hDoneDeliveringPoolLocal.WaitAll(); } //QuickThread::Myself().LowerPriority(); return(0); } int libusb_handle_events(libusb_context* ctx) { if (ctx == NULL) ctx = default_context; if (failguard::Abort()) return(LIBUSB_ERROR_INTERRUPTED); RAIIMutex lock (ctx->mutex); libusbemu_handle_isochronous(ctx, 60000); // 0 on success, or a LIBUSB_ERROR code on failure return(0); } int libusb_handle_events_timeout(libusb_context* ctx, struct timeval* timeout) { if (ctx == NULL) ctx = default_context; if (failguard::Abort()) return(LIBUSB_ERROR_INTERRUPTED); RAIIMutex lock (ctx->mutex); if (timeout == NULL) libusbemu_handle_isochronous(ctx, 0); else libusbemu_handle_isochronous(ctx, (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)); // 0 on success, or a LIBUSB_ERROR code on failure return(0); } void PreprocessTransferNaive(libusb_transfer* transfer, const int read); void PreprocessTransferFreenect(libusb_transfer* transfer, const int read); static void(*PreprocessTransfer)(libusb_transfer*, const int) (PreprocessTransferFreenect); void libusbemu_deliver_transfer(transfer_wrapper* wrapper) { // paranoid check... assert(libusb_device::TListTransfers::Orphan(wrapper)); libusb_transfer* transfer = &wrapper->libusb; // if data is effectively acquired (non-zero bytes transfer), all of the // associated iso packed descriptors must be filled properly; this is an // application specific task and requires knowledge of the logic behind // the streams being transferred: PreprocessTransfer() is an user-defined // "library-injected" routine that should perform this task. if (transfer->actual_length > 0) PreprocessTransfer(transfer, transfer->actual_length); // callback the library client through the callback; at this point, the // client is assumed to do whatever it wants to the data and, possibly, // resubmitting the transfer, which would then place the transfer at the // end of its related asynchronous list (orphan transfer is adopted). transfer->callback(transfer); } int ReapTransfer(transfer_wrapper*, unsigned int, libusb_device::TListTransfers*); int ReapThreadProc(void* params) { LIBUSB_DEBUG_CMD(fprintf(stdout, "Thread execution started.\n")); void** state = (void**)params; libusb_device_handle* dev_handle = (libusb_device_handle*)state[0]; const int endpoint = (int)state[1]; delete[](state); libusb_device::TMapIsocTransfers& isocTransfers = *(dev_handle->dev->isoTransfers); libusb_device::isoc_handle& isocHandle = isocTransfers[endpoint]; libusb_device::TListTransfers& listTransfers (isocHandle.listTransfers); QuickThread*& poThreadObject = isocHandle.poReapThread; libusb_context* ctx (dev_handle->dev->ctx); bool boAbort (false); bool boDeliverRequested (false); QuickEvent wannaDeliver; QuickEvent allowDeliver; QuickEvent doneDelivering; ctx->mutDeliveryPool.Enter(); ctx->hWantToDeliverPool.AttachEvent(&wannaDeliver); ctx->hAllowDeliveryPool.AttachEvent(&allowDeliver); ctx->hDoneDeliveringPool.AttachEvent(&doneDelivering); ctx->mutDeliveryPool.Leave(); libusb_device::TListTransfers listReadyLocal; // isochronous I/O must be handled in high-priority! (at least TIME_CRITICAL) // otherwise, sequence losses are prone to happen... QuickThread::Myself().RaisePriority(); // keep the thread alive as long as there are pending or ready transfers while(!listTransfers.Empty() || !listReadyLocal.Empty()) { // prioritize transfers that are ready to be delivered if (!listReadyLocal.Empty()) { // signal the delivery request, if not signaled yet if (!boDeliverRequested) { doneDelivering.Reset(); wannaDeliver.Signal(); boDeliverRequested = true; } // delivery request already signaled; wait for the delivery permission else if (allowDeliver.WaitUntilTimeout(1)) { boDeliverRequested = false; while (!listReadyLocal.Empty()) { transfer_wrapper* wrapper = listReadyLocal.Head(); listReadyLocal.Remove(wrapper); libusbemu_deliver_transfer(wrapper); } doneDelivering.Signal(); } } // check for pending transfers coming from the device stream if (!listTransfers.Empty()) { transfer_wrapper* wrapper = listTransfers.Head(); int read = ReapTransfer(wrapper, 10000, &listReadyLocal); if (-5 == read) { while (!listTransfers.Empty()) listTransfers.Remove(listTransfers.Head()); while (!listReadyLocal.Empty()) listReadyLocal.Remove(listReadyLocal.Head()); } } // if there are no pending transfers, wait the ready ones to be delivered else { LIBUSB_DEBUG_CMD(fprintf(stdout, "ReapThreadProc(): no pending transfers, sleeping until delivery...\n")); if (!boDeliverRequested) { doneDelivering.Reset(); wannaDeliver.Signal(); boDeliverRequested = true; } allowDeliver.Wait(); } // finally, check the thread failguard if (failguard::Check() && !boAbort) { failguard::WaitDecision(); if (failguard::Abort()) { LIBUSB_DEBUG_CMD(fprintf(stderr, "Thread is aborting: releasing transfers...\n")); QuickThread::Myself().LowerPriority(); boDeliverRequested = true; allowDeliver.Signal(); boAbort = true; } } } QuickThread::Myself().LowerPriority(); LIBUSB_DEBUG_CMD ( if (boAbort) fprintf(stderr, "Thread loop aborted.\n"); ); while(!ctx->mutDeliveryPool.TryEnter()) { wannaDeliver.Signal(); doneDelivering.Signal(); } ctx->hWantToDeliverPool.DetachEvent(&wannaDeliver); ctx->hAllowDeliveryPool.DetachEvent(&allowDeliver); ctx->hDoneDeliveringPool.DetachEvent(&doneDelivering); ctx->mutDeliveryPool.Leave(); poThreadObject = NULL; LIBUSB_DEBUG_CMD(fprintf(stdout, "Thread execution finished.\n")); return(0); } int ReapTransfer(transfer_wrapper* wrapper, unsigned int timeout, libusb_device::TListTransfers* lstReady) { void* context (wrapper->usb); libusb_transfer* transfer (&wrapper->libusb); const int read = usb_reap_async_nocancel(context, timeout); if (read >= 0) { // data successfully acquired (0 bytes is also a go!) transfer->status = LIBUSB_TRANSFER_COMPLETED; // according to the official libusb_transfer struct reference: // "int libusb_transfer::actual_length // Actual length of data that was transferred. // Read-only, and only for use within transfer callback function. // Not valid for isochronous endpoint transfers." // since the client will allegedly not read from this field, we'll be using // it here just to simplify the emulation implementation, more specifically // the libusb_handle_events() and libusbemu_clear_transfer(). transfer->actual_length = read; // the transfer should be removed from the head of the list and put into // an orphan state; it is up to the client code to resubmit the transfer // which will possibly happen during the client callback. libusb_device::TListTransfers::RemoveNode(wrapper); // two possibilities here: either deliver the transfer now or postpone the // delivery to keep it in sync with libusb_handle_events(); in the latter // case, a destination list must be provided. if (NULL != lstReady) lstReady->Append(wrapper); else libusbemu_deliver_transfer(wrapper); } else { // something bad happened: // (a) the timeout passed to usb_reap_async_nocancel() expired; // (b) the transfer was cancelled via usb_cancel_async(); // (c) some fatal error triggered. #undef EIO #undef EINVAL #undef ETIMEOUT enum EReapResult { EIO = -5, EINVAL = -22, ETIMEOUT = -116 }; switch(read) { // When usb_reap_async_nocancel() returns ETIMEOUT, then either: // (a) the timeout indeed expired; // (b) the transfer was cancelled. case ETIMEOUT : // when usb_reap_async_nocancel() returns ETIMEOUT, then either: // (a) the timeout indeed expired: in this case the transfer should // remain as the head of the transfer list (do not remove the node) // and silently return without calling back the client (or perhaps // set the transfer status to LIBUSB_TRANSFER_TIMED_OUT and then // call back - MORE INVESTIGATION REQUIRED) // (b) the transfer was cancelled: in this case the transfer should be // removed from the list and reported back through the callback. if (LIBUSB_TRANSFER_CANCELLED == transfer->status) { libusb_device::TListTransfers::RemoveNode(wrapper); for (int i=0; inum_iso_packets; ++i) transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_CANCELLED; transfer->callback(transfer); } break; case EINVAL : // I guess -22 is returned if one attempts to reap a context that does // not exist anymore (one that has already been deleted) LIBUSBEMU_ERROR_LIBUSBWIN32(); break; case EIO : // Error code -5 seems to be triggered when the device is lost... LIBUSBEMU_ERROR_LIBUSBWIN32(); libusb_device::TListTransfers::RemoveNode(wrapper); transfer->status = LIBUSB_TRANSFER_NO_DEVICE; transfer->callback(transfer); libusb_cancel_transfer(transfer); transfer->status = LIBUSB_TRANSFER_NO_DEVICE; break; default : // I have not stumbled into any other negative values coming from the // usb_reap_async_nocancel()... Anyway, cancel seems to be a simple yet // plausible preemptive approach... MORE INVESTIGATION NEEDED! LIBUSBEMU_ERROR_LIBUSBWIN32(); libusb_cancel_transfer(transfer); break; } } return(read); } // Naive transfer->iso_packet_desc array filler. It will probably never work // with any device, but it serves as a template and as a default handler... void PreprocessTransferNaive(libusb_transfer* transfer, const int read) { unsigned int remaining (read); const int pkts (transfer->num_iso_packets); for (int i=0; iiso_packet_desc[i]); desc.status = LIBUSB_TRANSFER_COMPLETED; desc.actual_length = MIN(remaining, desc.length); remaining -= desc.actual_length; } } // This is were the transfer->iso_packet_desc array is built. Knowledge of // the underlying device stream protocol is required in order to properly // setup this array. Moreover, it is also necessary to sneak into some of // the libfreenect internals so that the proper length of each iso packet // descriptor can be inferred. Fortunately, libfreenect has this information // avaliable in the "transfer->user_data" field which holds a pointer to a // fnusb_isoc_stream struct with all the information required in there. void PreprocessTransferFreenect(libusb_transfer* transfer, const int read) { fnusb_isoc_stream* xferstrm = (fnusb_isoc_stream*)transfer->user_data; freenect_device* dev = xferstrm->parent->parent; packet_stream* pktstrm = (transfer->endpoint == 0x81) ? &dev->video : &dev->depth; // Kinect Camera Frame Packet Header (12 bytes total): struct pkt_hdr { uint8_t magic[2]; uint8_t pad; uint8_t flag; uint8_t unk1; uint8_t seq; uint8_t unk2; uint8_t unk3; uint32_t timestamp; }; //packet sizes: // first middle last // Bayer 1920 1920 24 // IR 1920 1920 1180 // YUV422 1920 1920 36 // Depth 1760 1760 1144 const unsigned int pktlen = sizeof(pkt_hdr) + pktstrm->pkt_size; const unsigned int pktend = sizeof(pkt_hdr) + pktstrm->last_pkt_size; unsigned int remaining (read); unsigned int leftover (transfer->length); unsigned char* pktbuffer (transfer->buffer); const int pkts (transfer->num_iso_packets); for (int i=0; iiso_packet_desc[i]); desc.status = LIBUSB_TRANSFER_COMPLETED; const pkt_hdr& header (*(pkt_hdr*)pktbuffer); if ((header.magic[0] == 'R') && (header.magic[1] == 'B')) { switch(header.flag & 0x0F) { case 0x01 : // first frame packet case 0x02 : // intermediate frame packets desc.actual_length = MIN(remaining, pktlen); break; case 0x05 : // last frame packet desc.actual_length = MIN(remaining, pktend); break; default : fprintf(stdout, "0x%02X\n", header.flag); break; } } else { desc.actual_length = 0; } remaining -= desc.actual_length; pktbuffer += desc.length; // a.k.a: += 1920 leftover -= desc.length; // a.k.a: -= 1920 } LIBUSB_DEBUG_CMD ( if (remaining > 0) { fprintf(stdout, "%d remaining out of %d\n", remaining, read); if (remaining == read) fprintf(stdout, "no bytes consumed!\n"); } ); } libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/libusbemu_internal.h000066400000000000000000000250261264163024100272630ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libusbemu_threads.h" #include #include #include namespace libusbemu { template inline T*& SAFE_DELETE(T*& p) { if(NULL != p) delete(p); p = NULL; return(p); } template inline T MIN(const T& v1, const T& v2) { return((v1 struct QuickList { T ini; T end; QuickList() { memset(&ini, 0, sizeof(T)); memset(&end, 0, sizeof(T)); ini.prev = NULL; ini.next = &end; end.prev = &ini; end.next = NULL; } // copy-constructor is required to be safely used as a plain std::map value QuickList(const QuickList& rhs) { if (!rhs.Empty()) { fprintf(stdout, "WARNING: Copy-constructin from a non-empty QuickList!\n"); return; } memset(&ini, 0, sizeof(T)); memset(&end, 0, sizeof(T)); ini.prev = NULL; ini.next = &end; end.prev = &ini; end.next = NULL; } ~QuickList() {}; const bool Empty() const { return(ini.next == &end); // could also be (end.prev == &ini) } void Append(T* node) { if (!Orphan(node)) { fprintf(stdout, "WARNING: Appending non-orphan node to list...\n"); Remove(node); } end.prev->next = node; node->prev = end.prev; node->next = &end; end.prev = node; node->list = this; } T* Head() const { T* head (NULL); if (!Empty()) head = ini.next; return(head); } T* Last() const { T* last (NULL); if (!Empty()) last = end.prev; return(last); } const bool Member(T* node) const { return(this == node->list); } static T* Prev(T* node) { T* prev (NULL); if (NULL != node->prev->prev) prev = node->prev; return(prev); } static T* Next(T* node) { T* next (NULL); if (NULL != node->next->next) next = node->next; return(next); } const bool Remove (T* node) { if (!Member(node)) return(false); node->prev->next = node->next; node->next->prev = node->prev; node->prev = NULL; node->next = NULL; node->list = NULL; return(true); } static void RemoveNode(T* node) { if (Orphan(node)) return; node->list->Remove(node); } static const bool Orphan(T* node) { return(NULL == node->list); } }; template struct QuickListMutexed : QuickList { protected: // 'mutable' required to allow operations within 'const methods' mutable QuickMutex mutex; mutable QuickEvent chomp; // signals whether there is (or not) transfers in the list public: QuickListMutexed() {}; QuickListMutexed(const QuickListMutexed& rhs) : QuickList(rhs) {}; ~QuickListMutexed() { /*this->~QuickListMutexed()*/ mutex.Enter(); mutex.Leave(); }; const bool Empty() const { mutex.Enter(); const bool empty = QuickList::Empty(); mutex.Leave(); return(empty); } void Append(T* node) { mutex.Enter(); const bool empty = QuickList::Empty(); QuickList::Append(node); if (empty) chomp.Signal(); mutex.Leave(); } T* Head() const { mutex.Enter(); T* head = QuickList::Head(); mutex.Leave(); return(head); } T* Last() const { mutex.Enter(); T* last = QuickList::Last(); mutex.Leave(); return(last); } const bool Member(T* node) const { mutex.Enter(); const bool member = QuickList::Member(node); mutex.Leave(); return(member); } const bool Remove(T* node) { mutex.Enter(); const bool removed = QuickList::Remove(node); if (QuickList::Empty()) chomp.Reset(); mutex.Leave(); return(removed); } static const bool Orphan(T* node) { //node->list->mutex.Enter(); const bool orphan = QuickList::Orphan(node); //node->list->mutex.Leave(); return(orphan); } const bool WaitUntilTimeout(unsigned int milliseconds) const { return(chomp.WaitUntilTimeout(milliseconds)); } void Wait() const { chomp.Wait(); } const bool Check() const { return(chomp.Check()); } }; } // end of 'namespace libusbemu' using namespace libusbemu; struct transfer_wrapper { transfer_wrapper* prev; transfer_wrapper* next; QuickList* list; void* usb; libusb_transfer libusb; }; struct libusb_device_handle_t { libusb_device* dev; usb_dev_handle* handle; }; struct libusb_device_t { libusb_context* ctx; struct usb_device* device; int refcount; typedef QuickList TListTransfers; struct isoc_handle { TListTransfers listTransfers; QuickThread* poReapThread; }; typedef std::map TMapIsocTransfers; TMapIsocTransfers* isoTransfers; typedef std::map TMapHandles; TMapHandles* handles; }; struct libusb_context_t { typedef std::map TMapDevices; TMapDevices devices; QuickMutex mutex; QuickMutex mutDeliveryPool; EventList hWantToDeliverPool; EventList hAllowDeliveryPool; EventList hDoneDeliveringPool; }; #define LIBUSBEMU_ERROR(msg) libusbemu_report_error(__FILE__, __LINE__, msg) #define LIBUSBEMU_ERROR_LIBUSBWIN32() LIBUSBEMU_ERROR(usb_strerror()) namespace libusbemu { void libusbemu_report_error(const char* file, const int line, const char* msg) { // remove source file path: int i = strlen(file); while (-1 != --i) if ((file[i] == '/') || (file[i] == '\\')) break; file = &file[++i]; fprintf(stderr, "ERROR in libusbemu -- source file '%s' at line %d -- %s\n", file, line, msg); } transfer_wrapper* libusbemu_get_transfer_wrapper(libusb_transfer* transfer) { char* raw_address ((char*)transfer); char* off_address (raw_address - sizeof(void*) - 2*sizeof(transfer_wrapper*) - sizeof(QuickList*)); return((transfer_wrapper*)off_address); } libusb_device* libusbemu_register_device(libusb_context* ctx, struct usb_device* dev) { RAIIMutex lock (ctx->mutex); // register the device (if not already there) ... libusb_device dummy = { ctx, dev, 0, NULL, NULL }; libusb_context::TMapDevices::iterator it = ctx->devices.insert(std::make_pair(dev,dummy)).first; // ... and increment the reference count libusb_device& record (it->second); record.refcount++; // might as well do some paranoid checkings... assert(record.ctx == ctx); assert(record.device == dev); return(&(it->second)); } void libusbemu_unregister_device(libusb_device* dev) { libusb_context* ctx (dev->ctx); RAIIMutex lock (ctx->mutex); // decrement the reference count of the device ... --(dev->refcount); // ... and unregister device if the reference count reaches zero if (0 == dev->refcount) { SAFE_DELETE(dev->handles); // prior to device deletion, all of its transfer lists must be deleted if (NULL != dev->isoTransfers) { libusb_device::TMapIsocTransfers& allTransfers (*(dev->isoTransfers)); while (!allTransfers.empty()) { libusb_device::TMapIsocTransfers::iterator it (allTransfers.begin()); libusb_device::TListTransfers& listTransfers (it->second.listTransfers); while (!listTransfers.Empty()) { transfer_wrapper* transfer (listTransfers.Head()); // make it orphan so that it can be deleted: listTransfers.Remove(transfer); // the following will free the wrapper object as well: libusb_free_transfer(&transfer->libusb); } allTransfers.erase(it); } SAFE_DELETE(dev->isoTransfers); } ctx->devices.erase(dev->device); } } int libusbemu_setup_transfer(transfer_wrapper* wrapper) { void*& context = wrapper->usb; // paranoid check... if (NULL != context) return(LIBUSB_ERROR_OTHER); RAIIMutex lock (wrapper->libusb.dev_handle->dev->ctx->mutex); int ret (LIBUSB_ERROR_OTHER); libusb_transfer* transfer (&wrapper->libusb); usb_dev_handle* handle (transfer->dev_handle->handle); switch(transfer->type) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS : ret = usb_isochronous_setup_async(handle, &context, transfer->endpoint, transfer->iso_packet_desc[0].length); break; case LIBUSB_TRANSFER_TYPE_CONTROL : // libusb-0.1 does not actually support asynchronous control transfers, but this should be // very easy to emulate if necessary: just stick the transfer in a special list and then // libusb_handle_events() check if the list is empty or not; if it is not empty, a thread // is created temporarily just to deal with such control transfer requests until the list // becomes eventually empty again and the thread terminates. case LIBUSB_TRANSFER_TYPE_BULK : case LIBUSB_TRANSFER_TYPE_INTERRUPT : // these transfer types are not being used by libfreenect. they should be fairly simple to // emulate with libusb-0.1 since it already provides support for them. // usb_bulk_setup_async(translate(transfer->dev_handle), &context, transfer->endpoint); // usb_interrupt_setup_async(translate(transfer->dev_handle), &context, transfer->endpoint); default : return(LIBUSB_ERROR_INVALID_PARAM); } if (ret < 0) { // TODO: better error handling... // what do the functions usb_***_setup_async() actually return on error? LIBUSBEMU_ERROR_LIBUSBWIN32(); return(ret); } return(LIBUSB_SUCCESS); } void libusbemu_clear_transfer(transfer_wrapper* wrapper) { libusb_transfer* transfer (&wrapper->libusb); if (transfer->actual_length > 0) { transfer->actual_length = 0; memset(transfer->buffer, 0, transfer->length); for (int i=0; inum_iso_packets; ++i) transfer->iso_packet_desc[i].actual_length = 0; } } } // end of 'namespace libusbemu' libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/libusbemu_threads.h000066400000000000000000000040051264163024100270730ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once // Wrappers for platform-specific thread/synchronization objects: // * Thread // * Mutex (Critical Section) // * Events (Conditional Variables) #ifdef WIN32 // stick to the Windows scheme for now, but this structure could be easily // replaced by pthread for portability; however if real-time priority turns // out to be a requirement on that platform, the pthread implementation may // not have support for such scheduling. // for a much more lightweight run-time, this could be replaced by dummy // objects, provided that the library client is careful enough to avoid any // sort of race-conditions or dead-locks... #include "libusbemu_threads_win32.h" #else #error LIBUSBEMU PTHREAD WRAPPER NOT YET IMPLEMENTED! // #include "libusbemu_threads_pthread.h" #endif namespace libusbemu { struct RAIIMutex { QuickMutex& m_mutex; RAIIMutex(QuickMutex& mutex) : m_mutex(mutex) { m_mutex.Enter(); } ~RAIIMutex() { m_mutex.Leave(); } }; } libfreenect-0.5.3/platform/windows/libusb10emu/libusb-1.0/libusbemu_threads_win32.h000066400000000000000000000200111264163024100301100ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include #include #include #include namespace libusbemu { struct QuickEvent { friend struct EventList; private: HANDLE hEvent; public: inline QuickEvent(const bool signaled=false) : hEvent(NULL) { hEvent = CreateEvent(NULL, TRUE, (BOOL)signaled, NULL); } inline ~QuickEvent() { CloseHandle(hEvent); } inline void Signal() { SetEvent(hEvent); } inline void Reset() { ResetEvent(hEvent); } inline bool Check() { return(WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0)); } inline const bool WaitUntilTimeout(const unsigned int milliseconds) { return(WAIT_OBJECT_0 == WaitForSingleObject(hEvent, (DWORD)milliseconds)); } inline void Wait() { WaitUntilTimeout(INFINITE); } }; struct QuickThread { private: HANDLE hThread; // Type-safe wrapper that converts arbitrary function signatures into the // required signature of Win32 Thread Procedures (LPTHREAD_START_ROUTINE). // Any Win32 LPTHREAD_START_ROUTINE declared routine can be wrapped as well. // The wrapper is also capable of cleaning up itself upon thread termination. // This wrapper can be extended in the future to support member-functions // to run as thread procedures. template struct ThreadWrapper { struct State { F* routine; void* params; bool release; QuickThread* instance; QuickEvent* sigclone; }; static DWORD WINAPI Thunk(LPVOID lpParameter) { State state = *((State*)lpParameter); // clone state (no heap alloc!) state.sigclone->Signal(); // done cloning, signal back to creator state.sigclone = NULL; // start wrapped thread procedure DWORD ret = (DWORD)state.routine(state.params); // release the associated QuickThread instance if requested if (state.release) delete(state.instance); return(ret); } }; // allow the creation of pseudo-handles to the calling thread // this constructor cannot and should never be called explicitly! // use QuickThread::Myself() to spawn a pseudo-handle QuickThread inline QuickThread() : hThread(GetCurrentThread()) {} public: template inline QuickThread(F* proc, void* params, const bool auto_release=false) : hThread(NULL) { // the 'typename' is required here because of dependent names... // MSVC relaxes this constraint, but it goes against the standard. typename ThreadWrapper::State state; state.routine = proc; state.params = params; state.release = auto_release; state.instance = this; // in order to prevent heap allocation, an event is created so that the // thunk function can signal back when it is done cloning the state; this // may look like unnecessary overhead, but the less heap memory control, // the better becomes the management and maintenance of this class. QuickEvent hWaitThunkCloneState; state.sigclone = &hWaitThunkCloneState; // Ready to issue the thread creation: hThread = CreateThread(NULL, 0, &ThreadWrapper::Thunk, (LPVOID)&state, 0, NULL); // Wait for the thread thunk to clone the state... hWaitThunkCloneState.Wait(); // Event object will then be automatically released upon return } inline ~QuickThread() { // only if not a pseudo-handle... if (hThread == GetCurrentThread()) return; CloseHandle(hThread); } static inline QuickThread Myself() { return(QuickThread()); } inline void Join() { WaitForSingleObject(hThread, INFINITE); } inline bool TryJoin() { return(WAIT_OBJECT_0 == WaitForSingleObject(hThread, 0)); } inline bool LowerPriority() { return(TRUE == SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL)); } inline bool RaisePriority() { return(TRUE == SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL)); } static inline void Sleep(int milliseconds) { ::Sleep(milliseconds); } // Yield is already a Win32 macro (WinBase.h)... // http://winapi.freetechsecrets.com/win32/WIN32Yield.htm #ifdef Yield #undef Yield #endif // A pragma push/pop could be used instead, but it does not solve the issues // http://stackoverflow.com/questions/1793800/can-i-redefine-a-c-macro-for-a-few-includes-and-then-define-it-back //#pragma push_macro("Yield") //#undef Yield static inline void Yield() { // Sleep(0) or Sleep(1) ?! // http://stackoverflow.com/questions/1413630/switchtothread-thread-yield-vs-thread-sleep0-vs-thead-sleep1 ::Sleep(1); // could also use the following (but the semantics are quite shady...): // http://msdn.microsoft.com/en-us/library/ms686352(v=vs.85).aspx // SwitchToThread(); } //#pragma pop_macro("Yield") }; struct QuickMutex { private: CRITICAL_SECTION cs; public: inline QuickMutex() { InitializeCriticalSection(&cs); } inline ~QuickMutex() { DeleteCriticalSection(&cs); } inline const bool TryEnter() { return(0 != TryEnterCriticalSection(&cs)); } inline void Enter() { EnterCriticalSection(&cs); } inline void Leave() { LeaveCriticalSection(&cs); } }; struct EventList { QuickMutex mutex; std::vector m_vEvents; std::vector m_vHandles; EventList() {}; ~EventList() {}; const bool AttachEvent(QuickEvent* poEvent) { mutex.Enter(); m_vEvents.push_back(poEvent); m_vHandles.push_back(poEvent->hEvent); mutex.Leave(); return(true); } const bool DetachEvent(QuickEvent* poEvent) { mutex.Enter(); std::vector::iterator it1 = std::find(m_vEvents.begin(), m_vEvents.end(), poEvent); m_vEvents.erase(it1); std::vector::iterator it2 = std::find(m_vHandles.begin(), m_vHandles.end(), poEvent->hEvent); m_vHandles.erase(it2); mutex.Leave(); return(true); } int WaitAnyUntilTimeout(const unsigned int milliseconds) { int index (-1); mutex.Enter(); DWORD ret (WAIT_FAILED); const unsigned int nHandles (m_vHandles.size()); if (nHandles > 0) ret = WaitForMultipleObjects(nHandles, &m_vHandles[0], FALSE, milliseconds); if (ret - WAIT_OBJECT_0 < nHandles) index = (int)(ret - WAIT_OBJECT_0); mutex.Leave(); return(index); } int WaitAny() { return(WaitAnyUntilTimeout(INFINITE)); } int CheckAny() { return(WaitAnyUntilTimeout(0)); } const bool WaitAllUntilTimeout(const unsigned int milliseconds) { bool waited (false); mutex.Enter(); const unsigned int nHandles (m_vHandles.size()); if (nHandles > 0) waited = (WAIT_TIMEOUT != WaitForMultipleObjects(nHandles, &m_vHandles[0], FALSE, milliseconds)); mutex.Leave(); return(waited); } const bool WaitAll() { return(WaitAllUntilTimeout(INFINITE)); } QuickEvent* operator [] (const unsigned int index) { QuickEvent* poEvent (NULL); mutex.Enter(); poEvent = m_vEvents[index]; mutex.Leave(); return(poEvent); } }; } //end of 'namespace libusbemu' libfreenect-0.5.3/platform/windows/unistd.h000066400000000000000000000032761264163024100210050ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include #include // MinGW defines _SSIZE_T_DEFINED in sys/types.h when it defines ssize_t to be a long. // Redefining it causes an error. // MSVC does not define this. #ifndef _SSIZE_T_DEFINED #define _SSIZE_T_DEFINED typedef long ssize_t; #endif // _SSIZE_T_DEFINED static void usleep(__int64 usec) { // Convert to 100 nanosecond interval, negative for relative time. LARGE_INTEGER ft; ft.QuadPart = -(10 * usec); HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); WaitForSingleObject(timer, INFINITE); CloseHandle(timer); } libfreenect-0.5.3/src/000077500000000000000000000000001264163024100145675ustar00rootroot00000000000000libfreenect-0.5.3/src/CMakeLists.txt000066400000000000000000000043741264163024100173370ustar00rootroot00000000000000###################################################################################### # Build for main library ###################################################################################### include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${LIBUSB_1_INCLUDE_DIRS}) # Audio Firmware include(FindPythonInterp) IF(BUILD_REDIST_PACKAGE) # If this build is intended for a redistributable package, we can't include audios.bin, so we should include fwfetcher.py # and the package should run "python fwfetcher.py $INSTALL_PREFIX/share" as a postinst hook install (FILES "fwfetcher.py" DESTINATION "${CMAKE_INSTALL_PREFIX}/share") ELSE(BUILD_REDIST_PACKAGE) # If the install is local only, we can just run fwfetcher.py and install the audios.bin firmware to the system folder add_custom_target(firmware ALL COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/fwfetcher.py" "../audios.bin" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/fwfetcher.py") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/../audios.bin" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/libfreenect") ENDIF() LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c audio.c loader.c) add_library (freenect SHARED ${SRC}) set_target_properties ( freenect PROPERTIES VERSION ${PROJECT_VER} SOVERSION ${PROJECT_APIVER}) install (TARGETS freenect DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}") add_library (freenectstatic STATIC ${SRC}) set_target_properties (freenectstatic PROPERTIES OUTPUT_NAME freenect) IF(UNIX AND NOT APPLE) SET_TARGET_PROPERTIES (freenectstatic PROPERTIES COMPILE_FLAGS "-fPIC") ENDIF() install (TARGETS freenectstatic DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}") target_link_libraries (freenect ${LIBUSB_1_LIBRARIES}) target_link_libraries (freenectstatic ${LIBUSB_1_LIBRARIES}) # Install the header files install (FILES "../include/libfreenect.h" "../include/libfreenect_registration.h" "../include/libfreenect_audio.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) IF(UNIX) # Produce a pkg-config file for linking against the shared lib configure_file ("libfreenect.pc.in" "libfreenect.pc" @ONLY) install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libfreenect.pc" DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}/pkgconfig") ENDIF() libfreenect-0.5.3/src/audio.c000066400000000000000000000176271264163024100160510ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "libfreenect_audio.h" #include "freenect_internal.h" #include #include static void prepare_iso_out_data(freenect_device* dev, uint8_t* buffer) { audio_stream* stream = &dev->audio; if (dev->audio_out_cb) { // Then pull data from the ring buffer, calling the callback as needed to refill the buffer } else { memset(buffer, 0, 76); } ((uint16_t*)buffer)[0] = stream->out_window; buffer[2] = stream->out_seq; if (stream->out_window_parity == 0) { if (stream->out_counter_within_window < 4) { // madness type 1 - high nibble of buffer[3] should be the seq_in_window-th nibble of timestamp buffer[3] = (((stream->out_weird_timestamp >> (stream->out_counter_within_window*4)) & 0x000f) << 4) | 0x05; // I have no idea why we do this. } else if (stream->out_counter_within_window < 8) { // madness type 2 - same thing mod 4, but we add 23 to weird_timestamp for no clear reason. buffer[3] = ((((stream->out_weird_timestamp+23) >> ((stream->out_counter_within_window-4)*4)) & 0x000f) << 4) | 0x05; // I have even less idea why we do this. } else { buffer[3] = 0x01; // Oh, and then this. } } else { if (stream->out_counter_within_window < 4) { // madness type 1 buffer[3] = (((stream->out_weird_timestamp >> (stream->out_counter_within_window*4)) & 0x000f) << 4) | 0x05; // I have no idea why we do this. } else { buffer[3] = 0x01; } } // Now, update the values for their next usage: stream->out_seq++; stream->out_counter_within_window++; stream->out_weird_timestamp += (stream->out_window_parity == 1) ? 6 : 5; switch(stream->out_seq) { case 0x80: stream->out_seq = 0; // TODO: if we're at the beginning of a new outgoing window, save a timestamp case 0x2b: case 0x56: stream->out_counter_within_window = 0; stream->out_window++; stream->out_window_parity++; default: break; } if (stream->out_window_parity == 3) stream->out_window_parity = 0; return; } static void iso_out_callback(freenect_device *dev, uint8_t *pkt, int len) { prepare_iso_out_data(dev, pkt); } static void iso_in_callback(freenect_device *dev, uint8_t *pkt, int len) { freenect_context *ctx = dev->parent; if (len == 524) { // Cool, this is audio data audio_in_block* block = (audio_in_block*)pkt; if (block->magic != 0x80000080) { FN_ERROR("audio: invalid magic in iso IN packet: %08X\n", block->magic); return; } if (block->window != dev->audio.in_window) { FN_SPEW("audio: IN window changed: was %04X now %04X\n", dev->audio.in_window, block->window); if (dev->audio_in_cb) { dev->audio_in_cb(dev, 256, dev->audio.mic_buffer[0], dev->audio.mic_buffer[1], dev->audio.mic_buffer[2], dev->audio.mic_buffer[3], dev->audio.cancelled_buffer, dev->audio.in_unknown); } int t; for(t = 0; t < 10; t++) { if (dev->audio.last_seen_window[t] != dev->audio.in_window) { FN_SPEW("audio: did not receive data for channel 0x%02x\n", t+1); } } if (block->window - dev->audio.in_window > 3) { FN_SPEW("audio: packet loss, dropped %d windows\n", (block->window - dev->audio.in_window - 3) / 3); } dev->audio.in_window = block->window; } switch(block->channel) { case 1: memcpy(dev->audio.cancelled_buffer, &block->samples, 512); break; case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: if (block->channel & 1) { memcpy(&(dev->audio.mic_buffer[(block->channel-2) / 2][128]), &block->samples, 512); } else { memcpy(dev->audio.mic_buffer[(block->channel-2) / 2], &block->samples, 512); } break; default: FN_ERROR("audio: invalid channel in iso IN packet: %d\n", block->channel); break; } dev->audio.last_seen_window[block->channel-1] = block->window; } else if (len == 60) { // Then this is the uninterpreted signalling information } else if (len != 0) { FN_ERROR("audio: received an iso IN packet of strange length: %d\n", len); } } void freenect_set_audio_in_callback(freenect_device *dev, freenect_audio_in_cb callback) { dev->audio_in_cb = callback; } void freenect_set_audio_out_callback(freenect_device *dev, freenect_audio_out_cb callback) { dev->audio_out_cb = callback; } int freenect_start_audio(freenect_device* dev) { freenect_context *ctx = dev->parent; int res; if (dev->audio.running) return -1; // Allocate buffers dev->audio.audio_out_ring = (freenect_sample_51*)malloc(256 * sizeof(freenect_sample_51)); memset(dev->audio.audio_out_ring, 0, 256 * sizeof(freenect_sample_51)); dev->audio.cancelled_buffer = (int16_t*)malloc(256*sizeof(int16_t)); memset(dev->audio.cancelled_buffer, 0, 256*sizeof(int16_t)); int i; for(i = 0; i < 4; i++) { dev->audio.mic_buffer[i] = (int32_t*)malloc(256*sizeof(int32_t)); memset(dev->audio.mic_buffer[i], 0, 256*sizeof(int32_t)); } dev->audio.in_unknown = malloc(48); // amount of data in small transfer // Set initial parameter values dev->audio.ring_reader_idx = 0; dev->audio.ring_writer_idx = 0; dev->audio.out_window = 0; dev->audio.out_seq = 0; dev->audio.out_counter_within_window = 0; dev->audio.out_weird_timestamp = 0; dev->audio.out_window_parity = 0; dev->audio.in_window = 0; dev->audio.in_counter = 0; for(i = 0; i < 10; i++) { dev->audio.last_seen_window[i] = 0; } // Start isochronous streams res = fnusb_start_iso(&dev->usb_audio, &dev->audio_in_isoc, iso_in_callback, 0x82, NUM_XFERS, PKTS_PER_XFER, 524); if (res < 0) { FN_ERROR("audio: failed to start isochronous IN stream: %d\n", res); return res; } res = fnusb_start_iso(&dev->usb_audio, &dev->audio_out_isoc, iso_out_callback, 0x02, NUM_XFERS, PKTS_PER_XFER, 76); if (res < 0) { FN_ERROR("audio: failed to start isochronous OUT stream: %d\n", res); return res; } dev->audio.running = 1; return 0; } int freenect_stop_audio(freenect_device* dev) { freenect_context *ctx = dev->parent; int res; int ret = 0; if (!dev->audio.running) return -1; // Stop isochronous transfers // Note: I'm not sure how to make this work if there's partial failure. dev->audio.running = 0; res = fnusb_stop_iso(&dev->usb_audio, &dev->audio_in_isoc); if (res < 0) { FN_ERROR("audio: failed to stop isochronous IN stream: %d\n", res); return res; } res = fnusb_stop_iso(&dev->usb_audio, &dev->audio_out_isoc); if (res < 0) { FN_ERROR("audio: failed to stop isochronous OUT stream: %d\n", res); return res; } // Free buffers if (dev->audio.audio_out_ring) free(dev->audio.audio_out_ring); if (dev->audio.cancelled_buffer) free(dev->audio.cancelled_buffer); if (dev->audio.in_unknown) free(dev->audio.in_unknown); int i; for (i = 0; i < 4; i++) { if (dev->audio.mic_buffer[i]) free(dev->audio.mic_buffer[i]); dev->audio.mic_buffer[i] = NULL; } dev->audio.audio_out_ring = NULL; dev->audio.cancelled_buffer = NULL; dev->audio.in_unknown = NULL; return ret; } libfreenect-0.5.3/src/cameras.c000066400000000000000000001305151264163024100163530ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include "freenect_internal.h" #include "registration.h" #include "cameras.h" #include "flags.h" #define MAKE_RESERVED(res, fmt) (uint32_t)(((res & 0xff) << 8) | (((fmt & 0xff)))) #define RESERVED_TO_RESOLUTION(reserved) (freenect_resolution)((reserved >> 8) & 0xff) #define RESERVED_TO_FORMAT(reserved) ((reserved) & 0xff) #define video_mode_count 12 static freenect_frame_mode supported_video_modes[video_mode_count] = { // reserved, resolution, format, bytes, width, height, data_bits_per_pixel, padding_bits_per_pixel, framerate, is_valid {MAKE_RESERVED(FREENECT_RESOLUTION_HIGH, FREENECT_VIDEO_RGB), FREENECT_RESOLUTION_HIGH, {FREENECT_VIDEO_RGB}, 1280*1024*3, 1280, 1024, 24, 0, 10, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_RGB}, 640*480*3, 640, 480, 24, 0, 30, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_HIGH, FREENECT_VIDEO_BAYER), FREENECT_RESOLUTION_HIGH, {FREENECT_VIDEO_BAYER}, 1280*1024, 1280, 1024, 8, 0, 10, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_BAYER), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_BAYER}, 640*480, 640, 480, 8, 0, 30, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_HIGH, FREENECT_VIDEO_IR_8BIT), FREENECT_RESOLUTION_HIGH, {FREENECT_VIDEO_IR_8BIT}, 1280*1024, 1280, 1024, 8, 0, 10, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_IR_8BIT), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_IR_8BIT}, 640*488, 640, 488, 8, 0, 30, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_HIGH, FREENECT_VIDEO_IR_10BIT), FREENECT_RESOLUTION_HIGH, {FREENECT_VIDEO_IR_10BIT}, 1280*1024*2, 1280, 1024, 10, 6, 10, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_IR_10BIT), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_IR_10BIT}, 640*488*2, 640, 488, 10, 6, 30, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_HIGH, FREENECT_VIDEO_IR_10BIT_PACKED), FREENECT_RESOLUTION_HIGH, {FREENECT_VIDEO_IR_10BIT_PACKED}, 1280*1024*10/8, 1280, 1024, 10, 0, 10, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_IR_10BIT_PACKED), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_IR_10BIT_PACKED}, 640*488*10/8, 640, 488, 10, 0, 30, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_YUV_RGB), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_YUV_RGB}, 640*480*3, 640, 480, 24, 0, 15, 1 }, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_YUV_RAW), FREENECT_RESOLUTION_MEDIUM, {FREENECT_VIDEO_YUV_RAW}, 640*480*2, 640, 480, 16, 0, 15, 1 }, }; #define depth_mode_count 6 static freenect_frame_mode supported_depth_modes[depth_mode_count] = { // reserved, resolution, format, bytes, width, height, data_bits_per_pixel, padding_bits_per_pixel, framerate, is_valid {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT), FREENECT_RESOLUTION_MEDIUM, {FREENECT_DEPTH_11BIT}, 640*480*2, 640, 480, 11, 5, 30, 1}, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_10BIT), FREENECT_RESOLUTION_MEDIUM, {FREENECT_DEPTH_10BIT}, 640*480*2, 640, 480, 10, 6, 30, 1}, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT_PACKED), FREENECT_RESOLUTION_MEDIUM, {FREENECT_DEPTH_11BIT_PACKED}, 640*480*11/8, 640, 480, 11, 0, 30, 1}, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_10BIT_PACKED), FREENECT_RESOLUTION_MEDIUM, {FREENECT_DEPTH_10BIT_PACKED}, 640*480*10/8, 640, 480, 10, 0, 30, 1}, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_REGISTERED), FREENECT_RESOLUTION_MEDIUM, {FREENECT_DEPTH_REGISTERED}, 640*480*2, 640, 480, 16, 0, 30, 1}, {MAKE_RESERVED(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_MM), FREENECT_RESOLUTION_MEDIUM, {FREENECT_DEPTH_MM}, 640*480*2, 640, 480, 16, 0, 30, 1}, }; static const freenect_frame_mode invalid_mode = {0, (freenect_resolution)0, {(freenect_video_format)0}, 0, 0, 0, 0, 0, 0, 0}; struct pkt_hdr { uint8_t magic[2]; uint8_t pad; uint8_t flag; uint8_t unk1; uint8_t seq; uint8_t unk2; uint8_t unk3; uint32_t timestamp; }; static int stream_process(freenect_context *ctx, packet_stream *strm, uint8_t *pkt, int len, freenect_chunk_cb cb, void *user_data) { if (len < 12) return 0; struct pkt_hdr *hdr = (struct pkt_hdr*)pkt; uint8_t *data = pkt + sizeof(*hdr); int datalen = len - sizeof(*hdr); freenect_loglevel l_info = LL_INFO; freenect_loglevel l_notice = LL_NOTICE; freenect_loglevel l_warning = LL_WARNING; if (strm->valid_frames < 2) l_info = l_notice = l_warning = LL_SPEW; if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') { FN_LOG(l_notice, "[Stream %02x] Invalid magic %02x%02x\n", strm->flag, hdr->magic[0], hdr->magic[1]); return 0; } FN_FLOOD("[Stream %02x] Packet with flag: %02x\n", strm->flag, hdr->flag); uint8_t sof = strm->flag|1; uint8_t mof = strm->flag|2; uint8_t eof = strm->flag|5; // sync if required, dropping packets until SOF if (!strm->synced) { if (hdr->flag != sof) { FN_SPEW("[Stream %02x] Not synced yet...\n", strm->flag); return 0; } strm->synced = 1; strm->seq = hdr->seq; strm->pkt_num = 0; strm->valid_pkts = 0; strm->got_pkts = 0; } int got_frame_size = 0; // handle lost packets if (strm->seq != hdr->seq) { uint8_t lost = hdr->seq - strm->seq; strm->lost_pkts += lost; FN_LOG(l_info, "[Stream %02x] Lost %d packets\n", strm->flag, lost); FN_DEBUG("[Stream %02x] Lost %d total packets in %d frames (%f lppf)\n", strm->flag, strm->lost_pkts, strm->valid_frames, (float)strm->lost_pkts / strm->valid_frames); if (lost > 5 || strm->variable_length) { FN_LOG(l_notice, "[Stream %02x] Lost too many packets, resyncing...\n", strm->flag); strm->synced = 0; return 0; } strm->seq = hdr->seq; int left = strm->pkts_per_frame - strm->pkt_num; if (left <= lost) { strm->pkt_num = lost - left; strm->valid_pkts = strm->got_pkts; strm->got_pkts = 0; got_frame_size = strm->frame_size; strm->timestamp = strm->last_timestamp; strm->valid_frames++; } else { strm->pkt_num += lost; } } int expected_pkt_size = (strm->pkt_num == strm->pkts_per_frame-1) ? strm->last_pkt_size : strm->pkt_size; if (!strm->variable_length) { // check the header to make sure it's what we expect if (!(strm->pkt_num == 0 && hdr->flag == sof) && !(strm->pkt_num == strm->pkts_per_frame-1 && hdr->flag == eof) && !(strm->pkt_num > 0 && strm->pkt_num < strm->pkts_per_frame-1 && hdr->flag == mof)) { FN_LOG(l_notice, "[Stream %02x] Inconsistent flag %02x with %d packets in buf (%d total), resyncing...\n", strm->flag, hdr->flag, strm->pkt_num, strm->pkts_per_frame); strm->synced = 0; return got_frame_size; } // check data length if (datalen > expected_pkt_size) { FN_LOG(l_warning, "[Stream %02x] Expected max %d data bytes, but got %d. Dropping...\n", strm->flag, expected_pkt_size, datalen); return got_frame_size; } if (datalen < expected_pkt_size) FN_LOG(l_warning, "[Stream %02x] Expected %d data bytes, but got %d\n", strm->flag, expected_pkt_size, datalen); } else { // check the header to make sure it's what we expect if (!(strm->pkt_num == 0 && hdr->flag == sof) && !(strm->pkt_num < strm->pkts_per_frame && (hdr->flag == eof || hdr->flag == mof))) { FN_LOG(l_notice, "[Stream %02x] Inconsistent flag %02x with %d packets in buf (%d total), resyncing...\n", strm->flag, hdr->flag, strm->pkt_num, strm->pkts_per_frame); strm->synced = 0; return got_frame_size; } // check data length if (datalen > expected_pkt_size) { FN_LOG(l_warning, "[Stream %02x] Expected max %d data bytes, but got %d. Resyncng...\n", strm->flag, expected_pkt_size, datalen); strm->synced = 0; return got_frame_size; } if (datalen < expected_pkt_size && hdr->flag != eof) { FN_LOG(l_warning, "[Stream %02x] Expected %d data bytes, but got %d. Resyncing...\n", strm->flag, expected_pkt_size, datalen); strm->synced = 0; return got_frame_size; } } // copy or chunk process the data uint8_t *dbuf = strm->raw_buf + strm->pkt_num * strm->pkt_size; if(cb){ cb(strm->raw_buf,data,strm->pkt_num,datalen,user_data); }else{ memcpy(dbuf, data, datalen); } strm->pkt_num++; strm->seq++; strm->got_pkts++; strm->last_timestamp = fn_le32(hdr->timestamp); if (hdr->flag == eof) { if (strm->variable_length) got_frame_size = (dbuf - strm->raw_buf) + datalen; else got_frame_size = (dbuf - strm->raw_buf) + strm->last_pkt_size; strm->pkt_num = 0; strm->valid_pkts = strm->got_pkts; strm->got_pkts = 0; strm->timestamp = strm->last_timestamp; strm->valid_frames++; } return got_frame_size; } static void stream_init(freenect_context *ctx, packet_stream *strm, int rlen, int plen) { strm->valid_frames = 0; strm->synced = 0; if (strm->usr_buf) { strm->lib_buf = NULL; strm->proc_buf = strm->usr_buf; } else { strm->lib_buf = malloc(plen); strm->proc_buf = strm->lib_buf; } if (rlen == 0) { strm->split_bufs = 0; strm->raw_buf = (uint8_t*)strm->proc_buf; strm->frame_size = plen; } else { strm->split_bufs = 1; strm->raw_buf = (uint8_t*)malloc(rlen); strm->frame_size = rlen; } strm->last_pkt_size = strm->frame_size % strm->pkt_size; if (strm->last_pkt_size == 0) strm->last_pkt_size = strm->pkt_size; strm->pkts_per_frame = (strm->frame_size + strm->pkt_size - 1) / strm->pkt_size; } static void stream_freebufs(freenect_context *ctx, packet_stream *strm) { if (strm->split_bufs) free(strm->raw_buf); if (strm->lib_buf) free(strm->lib_buf); strm->raw_buf = NULL; strm->proc_buf = NULL; strm->lib_buf = NULL; } static int stream_setbuf(freenect_context *ctx, packet_stream *strm, void *pbuf) { if (!strm->running) { strm->usr_buf = pbuf; return 0; } else { if (!pbuf && !strm->lib_buf) { FN_ERROR("Attempted to set buffer to NULL but stream was started with no internal buffer\n"); return -1; } strm->usr_buf = pbuf; if (!pbuf) strm->proc_buf = strm->lib_buf; else strm->proc_buf = pbuf; if (!strm->split_bufs) strm->raw_buf = (uint8_t*)strm->proc_buf; return 0; } } /** * Convert a packed array of n elements with vw useful bits into array of * zero-padded 16bit elements. * * @param src The source packed array, of size (n * vw / 8) bytes * @param dest The destination unpacked array, of size (n * 2) bytes * @param vw The virtual width of elements, that is the number of useful bits for each of them * @param n The number of elements (in particular, of the destination array), NOT a length in bytes */ static inline void convert_packed_to_16bit(uint8_t *src, uint16_t *dest, int vw, int n) { unsigned int mask = (1 << vw) - 1; uint32_t buffer = 0; int bitsIn = 0; while (n--) { while (bitsIn < vw) { buffer = (buffer << 8) | *(src++); bitsIn += 8; } bitsIn -= vw; *(dest++) = (buffer >> bitsIn) & mask; } } /** * Convert a packed array of n elements with vw useful bits into array of * 8bit elements, dropping LSB. * * @param src The source packed array, of size (n * vw / 8) bytes * @param dest The destination unpacked array, of size (n * 2) bytes * @param vw The virtual width of elements, that is the number of useful bits for each of them * @param n The number of elements (in particular, of the destination array), NOT a length in bytes * * @pre vw is expected to be >= 8. */ static inline void convert_packed_to_8bit(uint8_t *src, uint8_t *dest, int vw, int n) { uint32_t buffer = 0; int bitsIn = 0; while (n--) { while (bitsIn < vw) { buffer = (buffer << 8) | *(src++); bitsIn += 8; } bitsIn -= vw; *(dest++) = buffer >> (bitsIn + vw - 8); } } // Loop-unrolled version of the 11-to-16 bit unpacker. n must be a multiple of 8. static void convert_packed11_to_16bit(uint8_t *raw, uint16_t *frame, int n) { uint16_t baseMask = (1 << 11) - 1; while(n >= 8) { uint8_t r0 = *(raw+0); uint8_t r1 = *(raw+1); uint8_t r2 = *(raw+2); uint8_t r3 = *(raw+3); uint8_t r4 = *(raw+4); uint8_t r5 = *(raw+5); uint8_t r6 = *(raw+6); uint8_t r7 = *(raw+7); uint8_t r8 = *(raw+8); uint8_t r9 = *(raw+9); uint8_t r10 = *(raw+10); frame[0] = (r0<<3) | (r1>>5); frame[1] = ((r1<<6) | (r2>>2) ) & baseMask; frame[2] = ((r2<<9) | (r3<<1) | (r4>>7) ) & baseMask; frame[3] = ((r4<<4) | (r5>>4) ) & baseMask; frame[4] = ((r5<<7) | (r6>>1) ) & baseMask; frame[5] = ((r6<<10) | (r7<<2) | (r8>>6) ) & baseMask; frame[6] = ((r8<<5) | (r9>>3) ) & baseMask; frame[7] = ((r9<<8) | (r10) ) & baseMask; n -= 8; raw += 11; frame += 8; } } static void depth_process(freenect_device *dev, uint8_t *pkt, int len) { freenect_context *ctx = dev->parent; if (len == 0) return; if (!dev->depth.running) return; int got_frame_size = stream_process(ctx, &dev->depth, pkt, len,dev->depth_chunk_cb,dev->user_data); if (!got_frame_size) return; FN_SPEW("Got depth frame of size %d/%d, %d/%d packets arrived, TS %08x\n", got_frame_size, dev->depth.frame_size, dev->depth.valid_pkts, dev->depth.pkts_per_frame, dev->depth.timestamp); switch (dev->depth_format) { case FREENECT_DEPTH_11BIT: convert_packed11_to_16bit(dev->depth.raw_buf, (uint16_t*)dev->depth.proc_buf, 640*480); break; case FREENECT_DEPTH_REGISTERED: freenect_apply_registration(dev, dev->depth.raw_buf, (uint16_t*)dev->depth.proc_buf ); break; case FREENECT_DEPTH_MM: freenect_apply_depth_to_mm(dev, dev->depth.raw_buf, (uint16_t*)dev->depth.proc_buf ); break; case FREENECT_DEPTH_10BIT: convert_packed_to_16bit(dev->depth.raw_buf, (uint16_t*)dev->depth.proc_buf, 10, 640*480); break; case FREENECT_DEPTH_10BIT_PACKED: case FREENECT_DEPTH_11BIT_PACKED: break; default: FN_ERROR("depth_process() was called, but an invalid depth_format is set\n"); break; } if (dev->depth_cb) dev->depth_cb(dev, dev->depth.proc_buf, dev->depth.timestamp); } #define CLAMP(x) if (x < 0) {x = 0;} if (x > 255) {x = 255;} static void convert_uyvy_to_rgb(uint8_t *raw_buf, uint8_t *proc_buf, freenect_frame_mode frame_mode) { int x, y; for(y = 0; y < frame_mode.height; ++y) { for(x = 0; x < frame_mode.width; x+=2) { int i = (frame_mode.width * y + x); int u = raw_buf[2*i]; int y1 = raw_buf[2*i+1]; int v = raw_buf[2*i+2]; int y2 = raw_buf[2*i+3]; int r1 = (y1-16)*1164/1000 + (v-128)*1596/1000; int g1 = (y1-16)*1164/1000 - (v-128)*813/1000 - (u-128)*391/1000; int b1 = (y1-16)*1164/1000 + (u-128)*2018/1000; int r2 = (y2-16)*1164/1000 + (v-128)*1596/1000; int g2 = (y2-16)*1164/1000 - (v-128)*813/1000 - (u-128)*391/1000; int b2 = (y2-16)*1164/1000 + (u-128)*2018/1000; CLAMP(r1) CLAMP(g1) CLAMP(b1) CLAMP(r2) CLAMP(g2) CLAMP(b2) proc_buf[3*i] =r1; proc_buf[3*i+1]=g1; proc_buf[3*i+2]=b1; proc_buf[3*i+3]=r2; proc_buf[3*i+4]=g2; proc_buf[3*i+5]=b2; } } } #undef CLAMP static void convert_bayer_to_rgb(uint8_t *raw_buf, uint8_t *proc_buf, freenect_frame_mode frame_mode) { int x,y; /* Pixel arrangement: * G R G R G R G R * B G B G B G B G * G R G R G R G R * B G B G B G B G * G R G R G R G R * B G B G B G B G * * To convert a Bayer-pattern into RGB you have to handle four pattern * configurations: * 1) 2) 3) 4) * B1 B1 G1 B2 R1 G1 R2 R1 <- previous line * R1 G1 R2 G2 R1 G3 G2 B1 G3 B1 G1 B2 <- current line * B2 B3 G4 B4 R3 G4 R4 R2 <- next line * ^ ^ ^ * | | next pixel * | current pixel * previous pixel * * The RGB values (r,g,b) for each configuration are calculated as * follows: * * 1) r = (R1 + R2) / 2 * g = G1 * b = (B1 + B2) / 2 * * 2) r = R1 * g = (G1 + G2 + G3 + G4) / 4 * b = (B1 + B2 + B3 + B4) / 4 * * 3) r = (R1 + R2 + R3 + R4) / 4 * g = (G1 + G2 + G3 + G4) / 4 * b = B1 * * 4) r = (R1 + R2) / 2 * g = G1 * b = (B1 + B2) / 2 * * To efficiently calculate these values, two 32bit integers are used * as "shift-buffers". One integer to store the 3 horizontal bayer pixel * values (previous, current, next) of the current line. The other * integer to store the vertical average value of the bayer pixels * (previous, current, next) of the previous and next line. * * The boundary conditions for the first and last line and the first * and last column are solved via mirroring the second and second last * line and the second and second last column. * * To reduce slow memory access, the values of a rgb pixel are packet * into a 32bit variable and transfered together. */ uint8_t *dst = proc_buf; // pointer to destination uint8_t *prevLine; // pointer to previous, current and next line uint8_t *curLine; // of the source bayer pattern uint8_t *nextLine; // storing horizontal values in hVals: // previous << 16, current << 8, next uint32_t hVals; // storing vertical averages in vSums: // previous << 16, current << 8, next uint32_t vSums; // init curLine and nextLine pointers curLine = raw_buf; nextLine = curLine + frame_mode.width; for (y = 0; y < frame_mode.height; ++y) { if ((y > 0) && (y < frame_mode.height-1)) prevLine = curLine - frame_mode.width; // normal case else if (y == 0) prevLine = nextLine; // top boundary case else nextLine = prevLine; // bottom boundary case // init horizontal shift-buffer with current value hVals = (*(curLine++) << 8); // handle left column boundary case hVals |= (*curLine << 16); // init vertical average shift-buffer with current values average vSums = ((*(prevLine++) + *(nextLine++)) << 7) & 0xFF00; // handle left column boundary case vSums |= ((*prevLine + *nextLine) << 15) & 0xFF0000; // store if line is odd or not uint8_t yOdd = y & 1; // the right column boundary case is not handled inside this loop // thus the "639" for (x = 0; x < frame_mode.width-1; ++x) { // place next value in shift buffers hVals |= *(curLine++); vSums |= (*(prevLine++) + *(nextLine++)) >> 1; // calculate the horizontal sum as this sum is needed in // any configuration uint8_t hSum = ((uint8_t)(hVals >> 16) + (uint8_t)(hVals)) >> 1; if (yOdd == 0) { if ((x & 1) == 0) { // Configuration 1 *(dst++) = hSum; // r *(dst++) = hVals >> 8; // g *(dst++) = vSums >> 8; // b } else { // Configuration 2 *(dst++) = hVals >> 8; *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1; *(dst++) = ((uint8_t)(vSums >> 16) + (uint8_t)(vSums)) >> 1; } } else { if ((x & 1) == 0) { // Configuration 3 *(dst++) = ((uint8_t)(vSums >> 16) + (uint8_t)(vSums)) >> 1; *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1; *(dst++) = hVals >> 8; } else { // Configuration 4 *(dst++) = vSums >> 8; *(dst++) = hVals >> 8; *(dst++) = hSum; } } // shift the shift-buffers hVals <<= 8; vSums <<= 8; } // end of for x loop // right column boundary case, mirroring second last column hVals |= (uint8_t)(hVals >> 16); vSums |= (uint8_t)(vSums >> 16); // the horizontal sum simplifies to the second last column value uint8_t hSum = (uint8_t)(hVals); if (yOdd == 0) { if ((x & 1) == 0) { *(dst++) = hSum; *(dst++) = hVals >> 8; *(dst++) = vSums >> 8; } else { *(dst++) = hVals >> 8; *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1; *(dst++) = vSums; } } else { if ((x & 1) == 0) { *(dst++) = vSums; *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1; *(dst++) = hVals >> 8; } else { *(dst++) = vSums >> 8; *(dst++) = hVals >> 8; *(dst++) = hSum; } } } // end of for y loop } static void video_process(freenect_device *dev, uint8_t *pkt, int len) { freenect_context *ctx = dev->parent; if (len == 0) return; if (!dev->video.running) return; int got_frame_size = stream_process(ctx, &dev->video, pkt, len,dev->video_chunk_cb,dev->user_data); if (!got_frame_size) return; FN_SPEW("Got video frame of size %d/%d, %d/%d packets arrived, TS %08x\n", got_frame_size, dev->video.frame_size, dev->video.valid_pkts, dev->video.pkts_per_frame, dev->video.timestamp); freenect_frame_mode frame_mode = freenect_get_current_video_mode(dev); switch (dev->video_format) { case FREENECT_VIDEO_RGB: convert_bayer_to_rgb(dev->video.raw_buf, (uint8_t*)dev->video.proc_buf, frame_mode); break; case FREENECT_VIDEO_BAYER: break; case FREENECT_VIDEO_IR_10BIT: convert_packed_to_16bit(dev->video.raw_buf, (uint16_t*)dev->video.proc_buf, 10, frame_mode.width * frame_mode.height); break; case FREENECT_VIDEO_IR_10BIT_PACKED: break; case FREENECT_VIDEO_IR_8BIT: convert_packed_to_8bit(dev->video.raw_buf, (uint8_t*)dev->video.proc_buf, 10, frame_mode.width * frame_mode.height); break; case FREENECT_VIDEO_YUV_RGB: convert_uyvy_to_rgb(dev->video.raw_buf, (uint8_t*)dev->video.proc_buf, frame_mode); break; case FREENECT_VIDEO_YUV_RAW: break; default: FN_ERROR("video_process() was called, but an invalid video_format is set\n"); break; } if (dev->video_cb) dev->video_cb(dev, dev->video.proc_buf, dev->video.timestamp); } static int freenect_fetch_reg_info(freenect_device *dev) { freenect_context *ctx = dev->parent; char reply[0x200]; uint16_t cmd[5]; freenect_frame_mode mode = freenect_get_current_video_mode(dev); cmd[0] = fn_le16(0x40); // ParamID - in this scenario, XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION cmd[1] = fn_le16(0); // Format cmd[2] = fn_le16((uint16_t)mode.resolution); // Resolution cmd[3] = fn_le16((uint16_t)mode.framerate); // FPS cmd[4] = fn_le16(0); // Offset int res; res = send_cmd(dev, 0x16, cmd, 10, reply, 118); // OPCODE_ALGORITHM_PARAMS if(res != 118) { FN_ERROR("freenect_fetch_reg_info: send_cmd read %d bytes (expected 118)\n", res); return -1; } memcpy(&dev->registration.reg_info, reply + 2, sizeof(dev->registration.reg_info)); dev->registration.reg_info.ax = fn_le32s(dev->registration.reg_info.ax); dev->registration.reg_info.bx = fn_le32s(dev->registration.reg_info.bx); dev->registration.reg_info.cx = fn_le32s(dev->registration.reg_info.cx); dev->registration.reg_info.dx = fn_le32s(dev->registration.reg_info.dx); dev->registration.reg_info.ay = fn_le32s(dev->registration.reg_info.ay); dev->registration.reg_info.by = fn_le32s(dev->registration.reg_info.by); dev->registration.reg_info.cy = fn_le32s(dev->registration.reg_info.cy); dev->registration.reg_info.dy = fn_le32s(dev->registration.reg_info.dy); dev->registration.reg_info.dx_start = fn_le32s(dev->registration.reg_info.dx_start); dev->registration.reg_info.dy_start = fn_le32s(dev->registration.reg_info.dy_start); dev->registration.reg_info.dx_beta_start = fn_le32s(dev->registration.reg_info.dx_beta_start); dev->registration.reg_info.dy_beta_start = fn_le32s(dev->registration.reg_info.dy_beta_start); dev->registration.reg_info.dx_beta_inc = fn_le32s(dev->registration.reg_info.dx_beta_inc); dev->registration.reg_info.dy_beta_inc = fn_le32s(dev->registration.reg_info.dy_beta_inc); dev->registration.reg_info.dxdx_start = fn_le32s(dev->registration.reg_info.dxdx_start); dev->registration.reg_info.dxdy_start = fn_le32s(dev->registration.reg_info.dxdy_start); dev->registration.reg_info.dydx_start = fn_le32s(dev->registration.reg_info.dydx_start); dev->registration.reg_info.dydy_start = fn_le32s(dev->registration.reg_info.dydy_start); dev->registration.reg_info.dxdxdx_start = fn_le32s(dev->registration.reg_info.dxdxdx_start); dev->registration.reg_info.dydxdx_start = fn_le32s(dev->registration.reg_info.dydxdx_start); dev->registration.reg_info.dxdxdy_start = fn_le32s(dev->registration.reg_info.dxdxdy_start); dev->registration.reg_info.dydxdy_start = fn_le32s(dev->registration.reg_info.dydxdy_start); dev->registration.reg_info.dydydx_start = fn_le32s(dev->registration.reg_info.dydydx_start); dev->registration.reg_info.dydydy_start = fn_le32s(dev->registration.reg_info.dydydy_start); FN_SPEW("ax: %d\n", dev->registration.reg_info.ax); FN_SPEW("bx: %d\n", dev->registration.reg_info.bx); FN_SPEW("cx: %d\n", dev->registration.reg_info.cx); FN_SPEW("dx: %d\n", dev->registration.reg_info.dx); FN_SPEW("ay: %d\n", dev->registration.reg_info.ay); FN_SPEW("by: %d\n", dev->registration.reg_info.by); FN_SPEW("cy: %d\n", dev->registration.reg_info.cy); FN_SPEW("dy: %d\n", dev->registration.reg_info.dy); FN_SPEW("dx_start: %d\n", dev->registration.reg_info.dx_start); FN_SPEW("dy_start: %d\n", dev->registration.reg_info.dy_start); FN_SPEW("dx_beta_start: %d\n", dev->registration.reg_info.dx_beta_start); FN_SPEW("dy_beta_start: %d\n", dev->registration.reg_info.dy_beta_start); FN_SPEW("dx_beta_inc: %d\n", dev->registration.reg_info.dx_beta_inc); FN_SPEW("dy_beta_inc: %d\n", dev->registration.reg_info.dy_beta_inc); FN_SPEW("dxdx_start: %d\n", dev->registration.reg_info.dxdx_start); FN_SPEW("dxdy_start: %d\n", dev->registration.reg_info.dxdy_start); FN_SPEW("dydx_start: %d\n", dev->registration.reg_info.dydx_start); FN_SPEW("dydy_start: %d\n", dev->registration.reg_info.dydy_start); FN_SPEW("dxdxdx_start: %d\n", dev->registration.reg_info.dxdxdx_start); FN_SPEW("dydxdx_start: %d\n", dev->registration.reg_info.dydxdx_start); FN_SPEW("dxdxdy_start: %d\n", dev->registration.reg_info.dxdxdy_start); FN_SPEW("dydxdy_start: %d\n", dev->registration.reg_info.dydxdy_start); FN_SPEW("dydydx_start: %d\n", dev->registration.reg_info.dydydx_start); FN_SPEW("dydydy_start: %d\n", dev->registration.reg_info.dydydy_start); /* // NOTE: Not assigned above FN_SPEW("dx_center: %d\n", dev_reg_info->dx_center); FN_SPEW("rollout_blank: %d\n", dev_reg_info->rollout_blank); FN_SPEW("rollout_size: %d\n", dev_reg_info->rollout_size); FN_SPEW("back_comp1: %d\n", dev_reg_info->back_comp1); FN_SPEW("back_comp2: %d\n", dev_reg_info->back_comp2); */ return 0; } static int freenect_fetch_reg_pad_info(freenect_device *dev) { freenect_context *ctx = dev->parent; char reply[0x200]; uint16_t cmd[5]; freenect_frame_mode mode = freenect_get_current_video_mode(dev); cmd[0] = fn_le16(0x41); // ParamID cmd[1] = fn_le16(0); // Format cmd[2] = fn_le16((uint16_t)mode.resolution); // Resolution cmd[3] = fn_le16((uint16_t)mode.framerate); // FPS cmd[4] = fn_le16(0); // Offset int res; res = send_cmd(dev, 0x16, cmd, 10, reply, 8); // OPCODE_ALGORITHM_PARAMS if(res != 8) { FN_ERROR("freenect_fetch_reg_pad_info: send_cmd read %d bytes (expected 8)\n", res); return -1; } memcpy(&dev->registration.reg_pad_info, reply+2, sizeof(dev->registration.reg_pad_info)); dev->registration.reg_pad_info.start_lines = fn_le16s(dev->registration.reg_pad_info.start_lines); dev->registration.reg_pad_info.end_lines = fn_le16s(dev->registration.reg_pad_info.end_lines); dev->registration.reg_pad_info.cropping_lines = fn_le16s(dev->registration.reg_pad_info.cropping_lines); FN_SPEW("start_lines: %u\n",dev->registration.reg_pad_info.start_lines); FN_SPEW("end_lines: %u\n",dev->registration.reg_pad_info.end_lines); FN_SPEW("cropping_lines: %u\n",dev->registration.reg_pad_info.cropping_lines); return 0; } static int freenect_fetch_reg_const_shift(freenect_device *dev) { freenect_context *ctx = dev->parent; char reply[0x200]; uint16_t cmd[5]; freenect_frame_mode mode = freenect_get_current_video_mode(dev); cmd[0] = fn_le16(0x00); // ParamID cmd[1] = fn_le16(0); // Format cmd[2] = fn_le16((uint16_t)mode.resolution); // Resolution cmd[3] = fn_le16((uint16_t)mode.framerate); // FPS cmd[4] = fn_le16(0); // Offset int res; res = send_cmd(dev, 0x16, cmd, 10, reply, 4); // OPCODE_ALGORITHM_PARAMS if(res != 4) { FN_ERROR("freenect_fetch_reg_const_shift: send_cmd read %d bytes (expected 8)\n", res); return -1; } uint16_t shift; memcpy(&shift, reply+2, sizeof(shift)); shift = fn_le16(shift); dev->registration.const_shift = (double)shift; FN_SPEW("const_shift: %f\n",dev->registration.const_shift); return 0; } static int freenect_fetch_zero_plane_info(freenect_device *dev) { freenect_context *ctx = dev->parent; char reply[0x200]; uint16_t cmd[5] = {0}; // Offset is the only field in this command, and it's 0 int res; res = send_cmd(dev, 0x04, cmd, 10, reply, ctx->zero_plane_res); //OPCODE_GET_FIXED_PARAMS = 4, if (res != ctx->zero_plane_res) { FN_ERROR("freenect_fetch_zero_plane_info: send_cmd read %d bytes (expected %d)\n", res,ctx->zero_plane_res); return -1; } memcpy(&(dev->registration.zero_plane_info), reply + 94, sizeof(dev->registration.zero_plane_info)); union { uint32_t ui; float f; } conversion_union; conversion_union.f = dev->registration.zero_plane_info.dcmos_emitter_dist; conversion_union.ui = fn_le32(conversion_union.ui); dev->registration.zero_plane_info.dcmos_emitter_dist = conversion_union.f; conversion_union.f = dev->registration.zero_plane_info.dcmos_rcmos_dist; conversion_union.ui = fn_le32(conversion_union.ui); dev->registration.zero_plane_info.dcmos_rcmos_dist = conversion_union.f; conversion_union.f = dev->registration.zero_plane_info.reference_distance; conversion_union.ui = fn_le32(conversion_union.ui); dev->registration.zero_plane_info.reference_distance = conversion_union.f; conversion_union.f = dev->registration.zero_plane_info.reference_pixel_size; conversion_union.ui = fn_le32(conversion_union.ui); dev->registration.zero_plane_info.reference_pixel_size = conversion_union.f; // WTF is all this data? it's way bigger than sizeof(XnFixedParams)... FN_SPEW("dcmos_emitter_distance: %f\n", dev->registration.zero_plane_info.dcmos_emitter_dist); FN_SPEW("dcmos_rcmos_distance: %f\n", dev->registration.zero_plane_info.dcmos_rcmos_dist); FN_SPEW("reference_distance: %f\n", dev->registration.zero_plane_info.reference_distance); FN_SPEW("reference_pixel_size: %f\n", dev->registration.zero_plane_info.reference_pixel_size); // FIXME: OpenNI seems to use a hardcoded value of 2.4 instead of 2.3 as reported by Kinect dev->registration.zero_plane_info.dcmos_rcmos_dist = 2.4f; return 0; } int freenect_start_depth(freenect_device *dev) { freenect_context *ctx = dev->parent; if (dev->depth.running) return -1; dev->depth.pkt_size = DEPTH_PKTDSIZE; dev->depth.flag = 0x70; dev->depth.variable_length = 0; switch (dev->depth_format) { case FREENECT_DEPTH_REGISTERED: case FREENECT_DEPTH_MM: freenect_init_registration(dev); case FREENECT_DEPTH_11BIT: stream_init(ctx, &dev->depth, freenect_find_depth_mode(dev->depth_resolution, FREENECT_DEPTH_11BIT_PACKED).bytes, freenect_find_depth_mode(dev->depth_resolution, FREENECT_DEPTH_11BIT).bytes); break; case FREENECT_DEPTH_10BIT: stream_init(ctx, &dev->depth, freenect_find_depth_mode(dev->depth_resolution, FREENECT_DEPTH_10BIT_PACKED).bytes, freenect_find_depth_mode(dev->depth_resolution, FREENECT_DEPTH_10BIT).bytes); break; case FREENECT_DEPTH_11BIT_PACKED: case FREENECT_DEPTH_10BIT_PACKED: stream_init(ctx, &dev->depth, 0, freenect_find_depth_mode(dev->depth_resolution, dev->depth_format).bytes); break; default: FN_ERROR("freenect_start_depth() called with invalid depth format %d\n", dev->depth_format); return -1; } const unsigned char depth_endpoint = 0x82; int packet_size = fnusb_get_max_iso_packet_size(&dev->usb_cam, depth_endpoint, DEPTH_PKTBUF); FN_INFO("[Stream 70] Negotiated packet size %d\n", packet_size); int res = fnusb_start_iso(&dev->usb_cam, &dev->depth_isoc, depth_process, depth_endpoint, NUM_XFERS, PKTS_PER_XFER, packet_size); if (res < 0) return res; write_register(dev, 0x105, 0x00); // Disable auto-cycle of projector write_register(dev, 0x06, 0x00); // reset depth stream switch (dev->depth_format) { case FREENECT_DEPTH_11BIT: case FREENECT_DEPTH_11BIT_PACKED: case FREENECT_DEPTH_REGISTERED: case FREENECT_DEPTH_MM: write_register(dev, 0x12, 0x03); break; case FREENECT_DEPTH_10BIT: case FREENECT_DEPTH_10BIT_PACKED: write_register(dev, 0x12, 0x02); break; case FREENECT_DEPTH_DUMMY: // Returned already, hush gcc break; } write_register(dev, 0x13, 0x01); write_register(dev, 0x14, 0x1e); write_register(dev, 0x06, 0x02); // start depth stream write_register(dev, 0x17, 0x00); // disable depth hflip dev->depth.running = 1; return 0; } int freenect_start_video(freenect_device *dev) { freenect_context *ctx = dev->parent; if (dev->video.running) return -1; dev->video.pkt_size = VIDEO_PKTDSIZE; dev->video.flag = 0x80; dev->video.variable_length = 0; uint16_t mode_reg, mode_value; uint16_t res_reg, res_value; uint16_t fps_reg, fps_value; uint16_t hflip_reg; switch(dev->video_format) { case FREENECT_VIDEO_RGB: case FREENECT_VIDEO_BAYER: if(dev->video_resolution == FREENECT_RESOLUTION_HIGH) { mode_value = 0x00; // Bayer res_value = 0x02; // 1280x1024 fps_value = 0x0f; // "15" Hz } else if (dev->video_resolution == FREENECT_RESOLUTION_MEDIUM) { mode_value = 0x00; // Bayer res_value = 0x01; // 640x480 fps_value = 0x1e; // 30 Hz } else { FN_ERROR("freenect_start_video(): called with invalid format/resolution combination\n"); return -1; } mode_reg = 0x0c; res_reg = 0x0d; fps_reg = 0x0e; hflip_reg = 0x47; break; case FREENECT_VIDEO_IR_8BIT: case FREENECT_VIDEO_IR_10BIT: case FREENECT_VIDEO_IR_10BIT_PACKED: if(dev->video_resolution == FREENECT_RESOLUTION_HIGH) { if(dev->depth.running) { FN_ERROR("freenect_start_video(): cannot stream high-resolution IR at same time as depth stream\n"); return -1; } // Due to some ridiculous condition in the firmware, we have to start and stop the // depth stream before the camera will hand us 1280x1024 IR. This is a stupid // workaround, but we've yet to find a better solution. write_register(dev, 0x13, 0x01); // set depth camera resolution (640x480) write_register(dev, 0x14, 0x1e); // set depth camera FPS (30) write_register(dev, 0x06, 0x02); // start depth camera write_register(dev, 0x06, 0x00); // stop depth camera mode_value = 0x00; // Luminance, 10-bit packed res_value = 0x02; // 1280x1024 fps_value = 0x0f; // "15" Hz } else if (dev->video_resolution == FREENECT_RESOLUTION_MEDIUM) { mode_value = 0x00; // Luminance, 10-bit packed res_value = 0x01; // 640x480 fps_value = 0x1e; // 30 Hz } else { FN_ERROR("freenect_start_video(): called with invalid format/resolution combination\n"); return -1; } mode_reg = 0x19; res_reg = 0x1a; fps_reg = 0x1b; hflip_reg = 0x48; break; case FREENECT_VIDEO_YUV_RGB: case FREENECT_VIDEO_YUV_RAW: if(dev->video_resolution == FREENECT_RESOLUTION_MEDIUM) { mode_value = 0x05; // UYUV mode res_value = 0x01; // 640x480 fps_value = 0x0f; // 15Hz } else { FN_ERROR("freenect_start_video(): called with invalid format/resolution combination\n"); return -1; } mode_reg = 0x0c; res_reg = 0x0d; fps_reg = 0x0e; hflip_reg = 0x47; break; default: FN_ERROR("freenect_start_video(): called with invalid video format %d\n", dev->video_format); return -1; } freenect_frame_mode frame_mode = freenect_get_current_video_mode(dev); switch (dev->video_format) { case FREENECT_VIDEO_RGB: stream_init(ctx, &dev->video, freenect_find_video_mode(dev->video_resolution, FREENECT_VIDEO_BAYER).bytes, frame_mode.bytes); break; case FREENECT_VIDEO_BAYER: stream_init(ctx, &dev->video, 0, frame_mode.bytes); break; case FREENECT_VIDEO_IR_8BIT: stream_init(ctx, &dev->video, freenect_find_video_mode(dev->video_resolution, FREENECT_VIDEO_IR_10BIT_PACKED).bytes, frame_mode.bytes); break; case FREENECT_VIDEO_IR_10BIT: stream_init(ctx, &dev->video, freenect_find_video_mode(dev->video_resolution, FREENECT_VIDEO_IR_10BIT_PACKED).bytes, frame_mode.bytes); break; case FREENECT_VIDEO_IR_10BIT_PACKED: stream_init(ctx, &dev->video, 0, frame_mode.bytes); break; case FREENECT_VIDEO_YUV_RGB: stream_init(ctx, &dev->video, freenect_find_video_mode(dev->video_resolution, FREENECT_VIDEO_YUV_RAW).bytes, frame_mode.bytes); break; case FREENECT_VIDEO_YUV_RAW: stream_init(ctx, &dev->video, 0, frame_mode.bytes); break; case FREENECT_VIDEO_DUMMY: // Silence compiler break; } const unsigned char video_endpoint = 0x81; int packet_size = fnusb_get_max_iso_packet_size(&dev->usb_cam, video_endpoint, VIDEO_PKTBUF); FN_INFO("[Stream 80] Negotiated packet size %d\n", packet_size); int res = fnusb_start_iso(&dev->usb_cam, &dev->video_isoc, video_process, video_endpoint, NUM_XFERS, PKTS_PER_XFER, packet_size); if (res < 0) return res; write_register(dev, mode_reg, mode_value); write_register(dev, res_reg, res_value); write_register(dev, fps_reg, fps_value); switch (dev->video_format) { case FREENECT_VIDEO_RGB: case FREENECT_VIDEO_BAYER: case FREENECT_VIDEO_YUV_RGB: case FREENECT_VIDEO_YUV_RAW: write_register(dev, 0x05, 0x01); // start video stream break; case FREENECT_VIDEO_IR_8BIT: case FREENECT_VIDEO_IR_10BIT: case FREENECT_VIDEO_IR_10BIT_PACKED: write_register(dev, 0x105, 0x00); // Disable auto-cycle of projector write_register(dev, 0x05, 0x03); // start video stream break; case FREENECT_VIDEO_DUMMY: // Silence compiler break; } write_register(dev, hflip_reg, 0x00); // disable Hflip dev->video.running = 1; return 0; } int freenect_stop_depth(freenect_device *dev) { freenect_context *ctx = dev->parent; int res; if (!dev->depth.running) return -1; dev->depth.running = 0; write_register(dev, 0x06, 0x00); // stop depth stream res = fnusb_stop_iso(&dev->usb_cam, &dev->depth_isoc); if (res < 0) { FN_ERROR("Failed to stop depth isochronous stream: %d\n", res); return res; } freenect_destroy_registration(&(dev->registration)); stream_freebufs(ctx, &dev->depth); return 0; } int freenect_stop_video(freenect_device *dev) { freenect_context *ctx = dev->parent; int res; if (!dev->video.running) return -1; dev->video.running = 0; write_register(dev, 0x05, 0x00); // stop video stream res = fnusb_stop_iso(&dev->usb_cam, &dev->video_isoc); if (res < 0) { FN_ERROR("Failed to stop RGB isochronous stream: %d\n", res); return res; } stream_freebufs(ctx, &dev->video); return 0; } void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb) { dev->depth_cb = cb; } void freenect_set_video_callback(freenect_device *dev, freenect_video_cb cb) { dev->video_cb = cb; } void freenect_set_depth_chunk_callback(freenect_device *dev, freenect_chunk_cb cb) { dev->depth_chunk_cb = cb; } void freenect_set_video_chunk_callback(freenect_device *dev, freenect_chunk_cb cb) { dev->video_chunk_cb = cb; } int freenect_get_video_mode_count() { return video_mode_count; } freenect_frame_mode freenect_get_video_mode(int mode_num) { if (mode_num >= 0 && mode_num < video_mode_count) return supported_video_modes[mode_num]; freenect_frame_mode retval; retval.is_valid = 0; return retval; } freenect_frame_mode freenect_get_current_video_mode(freenect_device *dev) { return freenect_find_video_mode(dev->video_resolution, dev->video_format); } freenect_frame_mode freenect_find_video_mode(freenect_resolution res, freenect_video_format fmt) { uint32_t unique_id = MAKE_RESERVED(res, fmt); int i; for(i = 0 ; i < video_mode_count; i++) { if (supported_video_modes[i].reserved == unique_id) return supported_video_modes[i]; } freenect_frame_mode retval; retval.is_valid = 0; return retval; } int freenect_set_video_mode(freenect_device* dev, const freenect_frame_mode mode) { freenect_context *ctx = dev->parent; if (dev->video.running) { FN_ERROR("Tried to set video mode while stream is active\n"); return -1; } // Verify that the mode passed in is actually in the supported mode list int found = 0; int i; for(i = 0 ; i < video_mode_count; i++) { if (supported_video_modes[i].reserved == mode.reserved) { found = 1; break; } } if (!found) { FN_ERROR("freenect_set_video_mode: freenect_frame_mode provided is invalid\n"); return -1; } freenect_resolution res = RESERVED_TO_RESOLUTION(mode.reserved); freenect_video_format fmt = (freenect_video_format)RESERVED_TO_FORMAT(mode.reserved); dev->video_format = fmt; dev->video_resolution = res; // Now that we've changed video format and resolution, we need to update // registration tables. freenect_fetch_reg_info(dev); return 0; } int freenect_get_depth_mode_count() { return depth_mode_count; } freenect_frame_mode freenect_get_depth_mode(int mode_num) { if (mode_num >= 0 && mode_num < depth_mode_count) return supported_depth_modes[mode_num]; freenect_frame_mode retval; retval.is_valid = 0; return retval; } freenect_frame_mode freenect_get_current_depth_mode(freenect_device *dev) { return freenect_find_depth_mode(dev->depth_resolution, dev->depth_format); } freenect_frame_mode freenect_find_depth_mode(freenect_resolution res, freenect_depth_format fmt) { uint32_t unique_id = MAKE_RESERVED(res, fmt); int i; for(i = 0 ; i < depth_mode_count; i++) { if (supported_depth_modes[i].reserved == unique_id) return supported_depth_modes[i]; } freenect_frame_mode retval; retval.is_valid = 0; return retval; } int freenect_set_depth_mode(freenect_device* dev, const freenect_frame_mode mode) { freenect_context *ctx = dev->parent; if (dev->depth.running) { FN_ERROR("Tried to set depth mode while stream is active\n"); return -1; } // Verify that the mode passed in is actually in the supported mode list int found = 0; int i; for(i = 0 ; i < depth_mode_count; i++) { if (supported_depth_modes[i].reserved == mode.reserved) { found = 1; break; } } if (!found) { FN_ERROR("freenect_set_depth_mode: freenect_frame_mode provided is invalid\n"); return -1; } freenect_resolution res = RESERVED_TO_RESOLUTION(mode.reserved); freenect_depth_format fmt = (freenect_depth_format)RESERVED_TO_FORMAT(mode.reserved); dev->depth_format = fmt; dev->depth_resolution = res; return 0; } int freenect_set_depth_buffer(freenect_device *dev, void *buf) { return stream_setbuf(dev->parent, &dev->depth, buf); } int freenect_set_video_buffer(freenect_device *dev, void *buf) { return stream_setbuf(dev->parent, &dev->video, buf); } FN_INTERNAL int freenect_camera_init(freenect_device *dev) { freenect_context *ctx = dev->parent; int res; res = freenect_fetch_reg_pad_info(dev); if (res < 0) { FN_ERROR("freenect_camera_init(): Failed to fetch registration pad info for device\n"); return res; } res = freenect_fetch_zero_plane_info(dev); if (res < 0) { FN_ERROR("freenect_camera_init(): Failed to fetch zero plane info for device\n"); return res; } res = freenect_set_video_mode(dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); res = freenect_set_depth_mode(dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); res = freenect_fetch_reg_const_shift(dev); if (res < 0) { FN_ERROR("freenect_camera_init(): Failed to fetch const shift for device\n"); return res; } return 0; } FN_INTERNAL int freenect_camera_teardown(freenect_device *dev) { freenect_context *ctx = dev->parent; int res = 0; if (dev->depth.running) { res = freenect_stop_depth(dev); if (res < 0) { FN_ERROR("freenect_camera_teardown(): Failed to stop depth camera\n"); } return res; } if (dev->video.running) { res = freenect_stop_video(dev); if (res < 0) { FN_ERROR("freenect_camera_teardown(): Failed to stop video camera\n"); } return res; } freenect_destroy_registration(&(dev->registration)); return 0; } libfreenect-0.5.3/src/cameras.h000066400000000000000000000025711264163024100163600ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010-2011 individual OpenKinect contributors. See the CONTRIB * file for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" // Just a couple function declarations. // These are called by core.c to do camera-specific initialization that needs // camera-specific protocol support. int freenect_camera_init(freenect_device *dev); int freenect_camera_teardown(freenect_device *dev); libfreenect-0.5.3/src/core.c000066400000000000000000000171121264163024100156650ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include #include "freenect_internal.h" #include "registration.h" #include "cameras.h" #include "loader.h" FREENECTAPI int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx) { int res; *ctx = (freenect_context*)malloc(sizeof(freenect_context)); if (*ctx == NULL) return -1; memset(*ctx, 0, sizeof(freenect_context)); (*ctx)->log_level = LL_WARNING; (*ctx)->enabled_subdevices = (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA); res = fnusb_init(&(*ctx)->usb, usb_ctx); if (res < 0) { free(*ctx); *ctx = NULL; } return res; } FREENECTAPI int freenect_shutdown(freenect_context *ctx) { while (ctx->first) { FN_NOTICE("Device %p open during shutdown, closing...\n", ctx->first); freenect_close_device(ctx->first); } fnusb_shutdown(&ctx->usb); free(ctx); return 0; } FREENECTAPI int freenect_process_events(freenect_context *ctx) { struct timeval timeout; timeout.tv_sec = 60; timeout.tv_usec = 0; return freenect_process_events_timeout(ctx, &timeout); } FREENECTAPI int freenect_process_events_timeout(freenect_context *ctx, struct timeval *timeout) { int res = fnusb_process_events_timeout(&ctx->usb, timeout); // Iterate over the devices in ctx. If any of them are flagged as freenect_device* dev = ctx->first; while(dev) { if (dev->usb_cam.device_dead) { FN_ERROR("USB camera marked dead, stopping streams\n"); res = -1; freenect_stop_video(dev); freenect_stop_depth(dev); } if (dev->usb_audio.device_dead) { FN_ERROR("USB audio marked dead, stopping streams\n"); res = -1; // Or something else to tell the user that the device just vanished. freenect_stop_audio(dev); } dev = dev->next; } return res; } FREENECTAPI int freenect_num_devices(freenect_context *ctx) { return fnusb_num_devices(&ctx->usb); } FREENECTAPI int freenect_list_device_attributes(freenect_context *ctx, struct freenect_device_attributes **attribute_list) { return fnusb_list_device_attributes(&ctx->usb, attribute_list); } FREENECTAPI void freenect_free_device_attributes(struct freenect_device_attributes *attribute_list) { // Iterate over list, freeing contents of each item as we go. struct freenect_device_attributes* to_free; while(attribute_list != NULL) { to_free = attribute_list; if (attribute_list->camera_serial != NULL) { free((char*)attribute_list->camera_serial); attribute_list->camera_serial = NULL; } attribute_list = attribute_list->next; free(to_free); } return; } FREENECTAPI int freenect_supported_subdevices(void) { return FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA | FREENECT_DEVICE_AUDIO; } FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs) { ctx->enabled_subdevices = (freenect_device_flags)(subdevs & (FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA | FREENECT_DEVICE_AUDIO)); } FREENECTAPI freenect_device_flags freenect_enabled_subdevices(freenect_context *ctx) { return ctx->enabled_subdevices; } FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index) { int res; freenect_device *pdev = (freenect_device*)malloc(sizeof(freenect_device)); if (!pdev) return -1; memset(pdev, 0, sizeof(*pdev)); pdev->parent = ctx; res = fnusb_open_subdevices(pdev, index); if (res < 0) { free(pdev); return res; } if (!ctx->first) { ctx->first = pdev; } else { freenect_device *prev = ctx->first; while (prev->next) prev = prev->next; prev->next = pdev; } *dev = pdev; // Do device-specific initialization if (pdev->usb_cam.dev) { if (freenect_camera_init(pdev) < 0) { return -1; } } return 0; } FREENECTAPI int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char* camera_serial) { // This is implemented by listing the devices and seeing which index (if // any) has a camera with a matching serial number, and then punting to // freenect_open_device with that index. struct freenect_device_attributes* attrlist; struct freenect_device_attributes* item; int count = fnusb_list_device_attributes(&ctx->usb, &attrlist); if (count < 0) { FN_ERROR("freenect_open_device_by_camera_serial: Couldn't enumerate serial numbers\n"); return count; } int index = 0; for(item = attrlist ; item != NULL; item = item->next , index++) { if (strlen(item->camera_serial) == strlen(camera_serial) && strcmp(item->camera_serial, camera_serial) == 0) { freenect_free_device_attributes(attrlist); return freenect_open_device(ctx, dev, index); } } freenect_free_device_attributes(attrlist); FN_ERROR("freenect_open_device_by_camera_serial: Couldn't find a device with serial %s\n", camera_serial); return -1; } FREENECTAPI int freenect_close_device(freenect_device *dev) { freenect_context *ctx = dev->parent; int res; if (dev->usb_cam.dev) { freenect_camera_teardown(dev); } res = fnusb_close_subdevices(dev); if (res < 0) { FN_ERROR("fnusb_close_subdevices failed: %d\n", res); return res; } freenect_device *last = NULL; freenect_device *cur = ctx->first; while (cur && cur != dev) { last = cur; cur = cur->next; } if (!cur) { FN_ERROR("device %p not found in linked list for this context!\n", dev); return -1; } if (last) last->next = cur->next; else ctx->first = cur->next; free(dev); return 0; } FREENECTAPI void freenect_set_user(freenect_device *dev, void *user) { dev->user_data = user; } FREENECTAPI void *freenect_get_user(freenect_device *dev) { return dev->user_data; } FREENECTAPI void freenect_set_log_level(freenect_context *ctx, freenect_loglevel level) { ctx->log_level = level; } FREENECTAPI void freenect_set_log_callback(freenect_context *ctx, freenect_log_cb cb) { ctx->log_cb = cb; } FN_INTERNAL void fn_log(freenect_context *ctx, freenect_loglevel level, const char *fmt, ...) { va_list ap; if (level > ctx->log_level) return; if (ctx->log_cb) { char msgbuf[1024]; va_start(ap, fmt); vsnprintf(msgbuf, 1024, fmt, ap); msgbuf[1023] = 0; va_end(ap); ctx->log_cb(ctx, level, msgbuf); } else { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } } FREENECTAPI void freenect_set_fw_address_nui(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes) { ctx->fn_fw_nui_ptr = fw_ptr; ctx->fn_fw_nui_size = num_bytes; } FREENECTAPI void freenect_set_fw_address_k4w(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes) { ctx->fn_fw_k4w_ptr = fw_ptr; ctx->fn_fw_k4w_size = num_bytes; } libfreenect-0.5.3/src/flags.c000066400000000000000000000163271264163024100160400ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010-2011 individual OpenKinect contributors. See the CONTRIB * file for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include // for memcpy #include // for usleep #include "freenect_internal.h" #include "flags.h" FN_INTERNAL int register_for_flag(int flag) { switch(flag) { case FREENECT_MIRROR_DEPTH: return 0x17; case FREENECT_MIRROR_VIDEO: return 0x47; default: return -1; } } int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value) { freenect_context *ctx = dev->parent; if (flag == FREENECT_NEAR_MODE) { if (dev->usb_cam.PID != PID_K4W_CAMERA) { FN_WARNING("Near mode is only supported by K4W"); return -1; } if (value == FREENECT_ON) { int ret = write_register(dev, 0x0015, 0x0007); if (ret < 0) return ret; usleep(100000); return write_register(dev, 0x02EF, 0x0000); } else { int ret = write_register(dev, 0x0015, 0x001E); if (ret < 0) return ret; usleep(100000); return write_register(dev, 0x02EF, 0x0190); } } if (flag >= (1 << 16)) { int reg = register_for_flag(flag); if (reg < 0) return reg; return write_register(dev, reg, value); } uint16_t cmos_value = read_cmos_register(dev, 0x0106); if (cmos_value == UINT16_MAX) { return -1; } if (value == FREENECT_ON) cmos_value |= flag; else cmos_value &= ~flag; return write_cmos_register(dev, 0x0106, cmos_value); } int freenect_get_ir_brightness(freenect_device *dev) { freenect_context *ctx = dev->parent; const uint16_t brightness = read_register(dev, 0x15); if (brightness == UINT16_MAX) { FN_WARNING("Failed to get IR brightness!"); return -1; } return brightness; } int freenect_set_ir_brightness(freenect_device *dev, uint16_t brightness) { freenect_context *ctx = dev->parent; if (brightness < 1) { brightness = 1; } if (brightness > 50) { brightness = 50; } const int ret = write_register(dev, 0x15, brightness); if (ret < 0) { FN_WARNING("Failed to set IR brightness"); } return ret; } typedef struct { uint8_t magic[2]; uint16_t len; uint16_t cmd; uint16_t tag; } cam_hdr; FN_INTERNAL int send_cmd(freenect_device *dev, uint16_t cmd, void *cmdbuf, unsigned int cmd_len, void *replybuf, int reply_len) { freenect_context *ctx = dev->parent; int res, actual_len; uint8_t obuf[0x400]; uint8_t ibuf[0x200]; cam_hdr *chdr = (cam_hdr*)obuf; cam_hdr *rhdr = (cam_hdr*)ibuf; if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) { FN_ERROR("send_cmd: Invalid command length (0x%x)\n", cmd_len); return -1; } chdr->magic[0] = 0x47; chdr->magic[1] = 0x4d; chdr->cmd = fn_le16(cmd); chdr->tag = fn_le16(dev->cam_tag); chdr->len = fn_le16(cmd_len / 2); memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len); res = fnusb_control(&dev->usb_cam, 0x40, 0, 0, 0, obuf, cmd_len + sizeof(*chdr)); FN_SPEW("send_cmd: cmd=%04x tag=%04x len=%04x: %d\n", cmd, dev->cam_tag, cmd_len, res); if (res < 0) { FN_ERROR("send_cmd: Output control transfer failed (%d)\n", res); return res; } do { actual_len = fnusb_control(&dev->usb_cam, 0xc0, 0, 0, 0, ibuf, 0x200); FN_FLOOD("send_cmd: actual length = %d\n", actual_len); } while ((actual_len == 0) || (actual_len == 0x200)); FN_SPEW("Control reply: %d\n", res); if (actual_len < (int)sizeof(*rhdr)) { FN_ERROR("send_cmd: Input control transfer failed (%d)\n", res); return res; } actual_len -= sizeof(*rhdr); if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) { FN_ERROR("send_cmd: Bad magic %02x %02x\n", rhdr->magic[0], rhdr->magic[1]); return -1; } if (rhdr->cmd != chdr->cmd) { FN_ERROR("send_cmd: Bad cmd %02x != %02x\n", rhdr->cmd, chdr->cmd); return -1; } if (rhdr->tag != chdr->tag) { FN_ERROR("send_cmd: Bad tag %04x != %04x\n", rhdr->tag, chdr->tag); return -1; } if (fn_le16(rhdr->len) != (actual_len/2)) { FN_ERROR("send_cmd: Bad len %04x != %04x\n", fn_le16(rhdr->len), (int)(actual_len/2)); return -1; } if (actual_len > reply_len) { FN_WARNING("send_cmd: Data buffer is %d bytes long, but got %d bytes\n", reply_len, actual_len); memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len); } else { memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len); } dev->cam_tag++; return actual_len; } // returns UINT16_MAX on error FN_INTERNAL uint16_t read_register(freenect_device *dev, uint16_t reg) { freenect_context *ctx = dev->parent; uint16_t reply[2]; uint16_t cmd = fn_le16(reg); int res = send_cmd(dev, 0x02, &cmd, 2, reply, 4); if (res < 0) { FN_ERROR("read_register: send_cmd() failed: %d\n", res); return UINT16_MAX; } if (res != 4) FN_WARNING("read_register: send_cmd() returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); FN_DEBUG("read_register: 0x%04x => 0x%04x\n", reg, reply[1]); return reply[1]; } FN_INTERNAL int write_register(freenect_device *dev, uint16_t reg, uint16_t data) { freenect_context *ctx = dev->parent; uint16_t reply[2]; uint16_t cmd[2]; cmd[0] = fn_le16(reg); cmd[1] = fn_le16(data); FN_DEBUG("write_register: 0x%04x <= 0x%02x\n", reg, data); int res = send_cmd(dev, 0x03, cmd, 4, reply, 4); if (res < 0) { FN_ERROR("write_register: send_cmd() returned %d\n", res); return res; } if (res != 2) FN_WARNING("write_register: send_cmd() returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); return 0; } // returns UINT16_MAX on error FN_INTERNAL uint16_t read_cmos_register(freenect_device *dev, uint16_t reg) { freenect_context *ctx = dev->parent; uint16_t replybuf[0x200]; uint16_t cmdbuf[3]; cmdbuf[0] = 1; cmdbuf[1] = reg & 0x7fff; cmdbuf[2] = 0; int res = send_cmd(dev, 0x95, cmdbuf, 6, replybuf, 6); if (res < 0) { FN_ERROR("read_cmos_register: send_cmd() returned %d\n", res); return UINT16_MAX; } FN_DEBUG("read_cmos_register: 0x%04x => 0x%04x\n", reg, replybuf[2]); return replybuf[2]; } FN_INTERNAL int write_cmos_register(freenect_device *dev, uint16_t reg, uint16_t value) { freenect_context *ctx = dev->parent; uint16_t replybuf[0x200]; uint16_t cmdbuf[3]; cmdbuf[0] = 1; cmdbuf[1] = reg | 0x8000; cmdbuf[2] = value; FN_DEBUG("write_cmos_register: 0x%04x <= 0x%04x\n", reg, value); int res = send_cmd(dev, 0x95, cmdbuf, 6, replybuf, 6); if (res < 0) FN_ERROR("write_cmos_register: send_cmd() returned %d\n", res); return res; } libfreenect-0.5.3/src/flags.h000066400000000000000000000031011264163024100160270ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010-2011 individual OpenKinect contributors. See the CONTRIB * file for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" int send_cmd(freenect_device *dev, uint16_t cmd, void *cmdbuf, unsigned int cmd_len, void *replybuf, int reply_len); // returns UINT16_MAX on error uint16_t read_register(freenect_device *dev, uint16_t reg); int write_register(freenect_device *dev, uint16_t reg, uint16_t data); // returns UINT16_MAX on error uint16_t read_cmos_register(freenect_device *dev, uint16_t reg); int write_cmos_register(freenect_device *dev, uint16_t reg, uint16_t value); libfreenect-0.5.3/src/freenect_internal.h000066400000000000000000000160071264163024100204330ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010-2011 individual OpenKinect contributors. See the CONTRIB * file for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include #include "libfreenect.h" #include "libfreenect_registration.h" #include "libfreenect_audio.h" #ifdef __ELF__ #define FN_INTERNAL __attribute__ ((visibility ("hidden"))) #else #define FN_INTERNAL #endif typedef void (*fnusb_iso_cb)(freenect_device *dev, uint8_t *buf, int len); #include "usb_libusb10.h" // needed to set the led state for non 1414 devices FN_INTERNAL int fnusb_set_led_alt(libusb_device_handle * dev, freenect_context * ctx, freenect_led_options state); struct _freenect_context { freenect_loglevel log_level; freenect_log_cb log_cb; fnusb_ctx usb; freenect_device_flags enabled_subdevices; freenect_device *first; int zero_plane_res; // if you want to load firmware from memory rather than disk unsigned char * fn_fw_nui_ptr; unsigned int fn_fw_nui_size; unsigned char * fn_fw_k4w_ptr; unsigned int fn_fw_k4w_size; }; #define LL_FATAL FREENECT_LOG_FATAL #define LL_ERROR FREENECT_LOG_ERROR #define LL_WARNING FREENECT_LOG_WARNING #define LL_NOTICE FREENECT_LOG_NOTICE #define LL_INFO FREENECT_LOG_INFO #define LL_DEBUG FREENECT_LOG_DEBUG #define LL_SPEW FREENECT_LOG_SPEW #define LL_FLOOD FREENECT_LOG_FLOOD #ifdef _WIN32 #include #include void fn_log(freenect_context *ctx, freenect_loglevel level, const char *fmt, ...); #else void fn_log(freenect_context *ctx, freenect_loglevel level, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); #endif #define FN_LOG(level, ...) fn_log(ctx, level, __VA_ARGS__) #define FN_FATAL(...) FN_LOG(LL_FATAL, __VA_ARGS__) #define FN_ERROR(...) FN_LOG(LL_ERROR, __VA_ARGS__) #define FN_WARNING(...) FN_LOG(LL_WARNING, __VA_ARGS__) #define FN_NOTICE(...) FN_LOG(LL_NOTICE, __VA_ARGS__) #define FN_INFO(...) FN_LOG(LL_INFO, __VA_ARGS__) #define FN_DEBUG(...) FN_LOG(LL_DEBUG, __VA_ARGS__) #define FN_SPEW(...) FN_LOG(LL_SPEW, __VA_ARGS__) #define FN_FLOOD(...) FN_LOG(LL_FLOOD, __VA_ARGS__) #ifdef FN_BIGENDIAN static inline uint16_t fn_le16(uint16_t d) { return (d<<8) | (d>>8); } static inline uint32_t fn_le32(uint32_t d) { return (d<<24) | ((d<<8)&0xFF0000) | ((d>>8)&0xFF00) | (d>>24); } static inline int16_t fn_le16s(int16_t s) { // reinterpret cast to unsigned, use the normal fn_le16, and then reinterpret cast back union { int16_t s; uint16_t u; } conversion_union; conversion_union.s = s; conversion_union.u = fn_le16(conversion_union.u); return conversion_union.s; } static inline int32_t fn_le32s(int32_t s) { // reinterpret cast to unsigned, use the normal fn_le32, and then reinterpret cast back union { int32_t s; uint32_t u; } conversion_union; conversion_union.s = s; conversion_union.u = fn_le32(conversion_union.u); return conversion_union.s; } #else #define fn_le16(x) (x) #define fn_le32(x) (x) #define fn_le16s(x) (x) #define fn_le32s(x) (x) #endif #define DEPTH_PKTSIZE 1760 #define VIDEO_PKTSIZE 1920 #define DEPTH_PKTDSIZE (DEPTH_PKTSIZE-12) #define VIDEO_PKTDSIZE (VIDEO_PKTSIZE-12) #define VID_MICROSOFT 0x45e #define PID_NUI_AUDIO 0x02ad #define PID_NUI_CAMERA 0x02ae #define PID_NUI_MOTOR 0x02b0 #define PID_K4W_CAMERA 0x02bf // For K4W: first pid is what it starts out as, // second is how it appears with lastest firmware from SDK, // third is from beta SDK firmware ( which is what is unpacked by the fw script and doesn't support motor control ) #define PID_K4W_AUDIO 0x02be #define PID_K4W_AUDIO_ALT_1 0x02c3 #define PID_K4W_AUDIO_ALT_2 0x02bb typedef struct { int running; uint8_t flag; int synced; uint8_t seq; int got_pkts; int pkt_num; int pkts_per_frame; int pkt_size; int frame_size; int last_pkt_size; int valid_pkts; unsigned int lost_pkts; int valid_frames; int variable_length; uint32_t last_timestamp; uint32_t timestamp; int split_bufs; void *lib_buf; void *usr_buf; uint8_t *raw_buf; void *proc_buf; } packet_stream; typedef struct { int running; freenect_sample_51* audio_out_ring; // TODO: implement sending user-provided data in callbacks int ring_reader_idx; // Index in audio_out_ring of the last sent sample int ring_writer_idx; // Index in audio_out_ring of the next sample we haven't received from the client yet uint16_t out_window; uint8_t out_seq; uint8_t out_counter_within_window; uint16_t out_weird_timestamp; uint8_t out_window_parity; uint16_t in_window; uint16_t last_seen_window[10]; uint8_t in_counter; int32_t* mic_buffer[4]; int16_t* cancelled_buffer; void* in_unknown; // TODO: timestamps } audio_stream; typedef struct { uint32_t magic; // 0x80000080 uint16_t channel; // Values between 0x1 and 0xa indicate audio channel uint16_t len; // packet length uint16_t window; // timestamp uint16_t unknown; // ??? int32_t samples[]; // Size depends on len } audio_in_block; typedef struct { uint16_t window; // Kinda like a timestamp. uint8_t seq; // Values from 0x00 to 0x7f uint8_t weird; // Has an odd cyclic behavior. freenect_sample_51 samples[6]; // Audio samples - 6 samples per transfer } audio_out_block; struct _freenect_device { freenect_context *parent; freenect_device *next; void *user_data; // Cameras fnusb_dev usb_cam; fnusb_isoc_stream depth_isoc; fnusb_isoc_stream video_isoc; freenect_depth_cb depth_cb; freenect_video_cb video_cb; freenect_chunk_cb depth_chunk_cb; freenect_chunk_cb video_chunk_cb; freenect_video_format video_format; freenect_depth_format depth_format; freenect_resolution video_resolution; freenect_resolution depth_resolution; int cam_inited; uint16_t cam_tag; packet_stream depth; packet_stream video; // Registration freenect_registration registration; // Audio fnusb_dev usb_audio; fnusb_isoc_stream audio_out_isoc; fnusb_isoc_stream audio_in_isoc; freenect_audio_in_cb audio_in_cb; freenect_audio_out_cb audio_out_cb; audio_stream audio; uint32_t audio_tag; // Motor fnusb_dev usb_motor; freenect_raw_tilt_state raw_state; int device_does_motor_control_with_audio; int motor_control_with_audio_enabled; }; libfreenect-0.5.3/src/fwfetcher.py000066400000000000000000000465031264163024100171260ustar00rootroot00000000000000#!/usr/bin/env python2 from urllib2 import Request, urlopen, URLError import hashlib import os import StringIO import struct import sys import time import zipfile # fwfetcher.py - a program to extract the Kinect audio firmware from an Xbox360 # system update. This program includes substantial portions of extract360.py, # which is copyright Rene Ladan and others as noted below and provided under # the BSD 2-clause license. """Program to extract typical XBox 360 files. It can handle LIVE/PIRS, CON (partially), FMIM, and XUIZ files. What about CRA (aka .arc) files? (Dead Rising demo) Copyright (c) 2007, 2008, Rene Ladan , 2-claused BSD license. Portions from various contributors as mentioned in-source. Note that it dumps UTF-16 characters in text strings as-is. """ ################################################################################ def check_size(fsize, minsize): """Ensure that the filesize is at least minsize bytes. @param fsize the filesize @param minsize the minimal file size @return fsize >= minsize """ if fsize < minsize: print "Input file too small: %i instead of at least %i bytes." % \ (fsize, minsize) return fsize >= minsize ################################################################################ def nice_open_file(filename): """Checks if the output file with the given name already exists, and if so, asks for overwrite permission. @param filename name of the output file to open @return overwrite permission """ if os.path.isfile(filename): print filename, "already exists, overwrite? (y/n)", answer = raw_input("") return len(answer) > 0 and answer[0] in ["Y", "y"] else: return True ################################################################################ def nice_open_dir(dirname): """Checks if the output directory with the given name already exists, and if so, asks for overwrite permission. This means that any file in that directory might be overwritten. @param dirname name of the output directory to open @return overwrite permission """ if os.path.isdir(dirname): print dirname, "already exists, ok to overwrite files in it? (y/n)", answer = raw_input("") return len(answer) > 0 and answer[0] in ["Y", "y"] else: return True ################################################################################ def do_mkdir(dirname): """Version of os.mkdir() which does not throw an exception if the directory already exists. @param dirname name of the directory to create """ try: os.mkdir(dirname) except OSError, (errno): if errno == 17: pass # directory already exists ################################################################################ def strip_blanks(instring): """Strip the leading and trailing blanks from the input string. Blanks are: 0x00 (only trailing) space \t \n \r \v \f 0xFF @param instring the input string @return stripped version of instring """ rstr = instring.rstrip("\0 \t\n\r\v\f\377") return rstr.lstrip(" \t\n\r\v\f\377") ################################################################################ def open_info_file(infile): """Open the informational text file. The name is based on that of the input file. @param infile pointer to the input file @return pointer to the informational text file or None if there was no overwrite permission """ txtname = os.path.basename(infile.name) + ".txt" if nice_open_file(txtname): print "Writing information file", txtname txtfile = open(txtname, "w") return txtfile else: return None ################################################################################ def dump_png(infile, pnglen, maxlen, pngid): """Dump the embedded PNG file from the archive file to an output file. @param infile pointer to the archive file @param pnglen size of the PNG file in bytes @param maxlen maximum size of the PNG file in bytes @param pngid indicates if this is the first or second PNG file. """ # dump PNG icon if pnglen <= maxlen: outname = os.path.basename(infile.name) + "_" + pngid + ".png" if nice_open_file(outname): buf = infile.read(pnglen) print "Writing PNG file", outname outfile = open(outname, "wb") print >> outfile, buf, outfile.close() else: print "PNG image %s too large (%i instead of maximal %i bytes), " \ "file not written." % (pngid, pnglen, maxlen) ################################################################################ def dump_info(infile, txtfile, what): """Dumps the 9 information strings from the input file. @param infile pointer to the input file @param txtfile pointer to the resulting text file @param what indicates if the information consists of titles or descriptions """ print >> txtfile, "\n", what, ":" for i in xrange(9): info = strip_blanks(infile.read(0x100)) if len(info) > 0: print >> txtfile, lang[i], ":", info ################################################################################ def mstime(intime): """Convert the time given in Microsoft format to a normal time tuple. @param intime the time in Microsoft format @return the time tuple """ num_d = (intime & 0xFFFF0000L) >> 16 num_t = intime & 0x0000FFFFL # format below is : year, month, day, hour, minute, second, # weekday (Monday), yearday (unused), DST flag (guess) return ((num_d >> 9) + 1980, (num_d >> 5) & 0x0F, num_d & 0x1F, (num_t & 0xFFFF) >> 11, (num_t >> 5) & 0x3F, (num_t & 0x1F) * 2, 0, 0, -1) ################################################################################ def do_utime(targetname, atime, mtime): """Set the access and update date/time of the target. Taken from tarfile.py (builtin lib) @param targetname name of the target @param atime the desired access date/time @param mtime the desired update date/time """ if not hasattr(os, "utime"): return if not (sys.platform == "win32" and os.path.isdir(targetname)): # Using utime() on directories is not allowed on Win32 according to # msdn.microsoft.com os.utime(targetname, (time.mktime(mstime(atime)), time.mktime(mstime(mtime)))) ################################################################################ def check_sha1(sha1, entry, infile, start, end): """Check the SHA1 value of the specified range of the input file. @param sha1 the reported SHA1 value @param entry the id of the hash @param infile the input file to check @param start the start position @param end the end position @return string reporting if the hash is correct """ infile.seek(start) found_sha1 = hashlib.sha1(infile.read(end - start)) found_digest = found_sha1.digest() # SHA1 hashes are 20 bytes (160 bits) long ret = "SHA1 " + hex(entry) + " " if found_digest == sha1: return ret + "ok (" + found_sha1.hexdigest() + ")" else: hexdig = "" for i in sha1: if ord(i) < 10: val = "0" else: val = "" val += hex(ord(i))[2:] hexdig += val return ret + "wrong (should be " + hexdig + " actual " + \ found_sha1.hexdigest() + ")" ################################################################################ def get_cluster(startclust, offset): """get the real starting cluster""" rst = 0 # BEGIN wxPirs while startclust >= 170: startclust //= 170 rst += (startclust + 1) * offset # END wxPirs return rst ################################################################################ def fill_directory(infile, txtfile, contents, firstclust, makedir, start, offset): """Fill the directory structure with the files contained in the archive. @param infile pointer to the archive @param txtfile pointer to the resulting information text file @param contents contains the directory information @param firstclust address of the starting cluster of the first file in infile (in 4kB blocks, minus start bytes) @param makedir flag if directory should be filled, useful if only return is wanted @param start start of directory data @param offset increment for calculating real starting cluster """ # dictionary which holds the directory structure, # patch 0xFFFF is the 'root' directory. paths = {0xFFFF:""} oldpathind = 0xFFFF # initial path, speed up file/dir creation for i in xrange(0x1000 * firstclust // 64): cur = contents[i * 64:(i + 1) * 64] if ord(cur[40]) == 0: # if filename length is zero, we're done break (outname, namelen, clustsize1, val1, clustsize2, val2, startclust, val3) = struct.unpack("<40sBHBHBHB", cur[0:50]) # sizes and starting cluster are 24 bits long clustsize1 += val1 << 16 clustsize2 += val2 << 16 startclust += val3 << 16 (pathind, filelen, dati1, dati2) = struct.unpack(">HLLL", cur[50:64]) if not makedir: continue nlen = namelen & ~0xC0 if nlen < 1 or nlen > 40: print "Filename length (%i) out of range, skipping file." % nlen continue outname = outname[0:nlen] # strip trailing 0x00 from filename if txtfile != None: if namelen & 0x80 == 0x80: print >> txtfile, "Directory", else: print >> txtfile, "File", print >> txtfile, "name:", outname if namelen & 0x40 == 0x40: print >> txtfile, "Bit 6 of namelen is set." if clustsize1 != clustsize2: print "Cluster sizes don't match (%i != %i), skipping file." % \ (clustsize1, clustsize2) continue if startclust < 1 and namelen & 0x80 == 0: print "Starting cluster must be 1 or greater, skipping file." continue if filelen > 0x1000 * clustsize1: print "File length (%i) is greater than the size in clusters " \ "(%i), skipping file." % (filelen, clustsize1) continue if pathind != oldpathind: # working directory changed for _ in xrange(paths[oldpathind].count("/")): os.chdir("..") # go back to root directory os.chdir(paths[pathind]) oldpathind = pathind if namelen & 0x80 == 0x80: # this is a directory paths[i] = paths[pathind] + outname + "/" do_mkdir(outname) else: # this is a file # space between files is set to 0x00 adstart = startclust * 0x1000 + start if txtfile != None: print >> txtfile, "Starting: advertized", hex(adstart) # block reading algorithm originally from wxPirs buf = "" while filelen > 0: realstart = adstart + get_cluster(startclust, offset) infile.seek(realstart) buf += infile.read(min(0x1000, filelen)) startclust += 1 adstart += 0x1000 filelen -= 0x1000 outfile = open(outname, "wb") print >> outfile, buf, outfile.close() do_utime(outname, dati2, dati1) # pop directory for _ in xrange(paths[oldpathind].count("/")): os.chdir("..") ################################################################################ def write_common_part(infile, txtfile, png2stop, start): """Writes out the common part of PIRS/LIVE and CON files. @param infile pointer to the PIRS/LIVE or CON file @param txtfile pointer to the resulting text file @param png2stop location where the second PNG image stops (PIRS/LIVE : 0xB000, CON : 0xA000) @param start start of directory data, from wxPirs """ infile.seek(0x32C) mhash = infile.read(20) # xbox180 : SHA1 hash of 0x0344-0xB000, # CON : 0x0344 - 0xA000 (i.e. png2stop) (mentry_id, content_type) = struct.unpack(">LL", infile.read(8)) if txtfile != None: print >> txtfile, "\nMaster SHA1 hash :", \ check_sha1(mhash, mentry_id, infile, 0x0344, png2stop) print >> txtfile, "\nContent type", hex(content_type), ":", # content type list partially from V1kt0R # su20076000_00000000 has type 0x000b0000, # i.e. "Full game demo" & "Theme" ... if content_type == 0: print >> txtfile, "(no type)" elif content_type & 0x00000001: print >> txtfile, "Game save" elif content_type & 0x00000002: print >> txtfile, "Game add-on" elif content_type & 0x00030000: print >> txtfile, "Theme" elif content_type & 0x00090000: print >> txtfile, "Video clip" elif content_type & 0x000C0000: print >> txtfile, "Game trailer" elif content_type & 0x000D0000: print >> txtfile, "XBox Live Arcade" elif content_type & 0x00010000: print >> txtfile, "Gamer profile" elif content_type & 0x00020000: print >> txtfile, "Gamer picture" elif content_type & 0x00040000: print >> txtfile, "System update" elif content_type & 0x00080000: print >> txtfile, "Full game demo" else: print >> txtfile, "(unknown)" print >> txtfile, "\nDirectory data at (hex)", hex(start) infile.seek(0x410) dump_info(infile, txtfile, "Titles") dump_info(infile, txtfile, "Descriptions") print >> txtfile, "\nPublisher:", strip_blanks(infile.read(0x80)), "\n" print >> txtfile, "\nFilename:", strip_blanks(infile.read(0x80)), "\n" infile.seek(0x1710) (val1, png1len, png2len) = struct.unpack(">HLL", infile.read(10)) if txtfile != None: print >> txtfile, "Value:", val1 if png1len > 0: dump_png(infile, png1len, 0x571A - 0x171A, "1") if png2len > 0: infile.seek(0x571A) dump_png(infile, png2len, png2stop - 0x571A, "2") # entries are 64 bytes long # unused entries are set to 0x00 infile.seek(start + 0x2F) (firstclust, ) = struct.unpack("> txtfile infile.seek(png2stop) buf = infile.read(start - png2stop) numempty = 0 for i in xrange(len(buf) // 24): entry = buf[i * 24: i * 24 + 24] if entry.count("\0") < 24: if numempty > 0: print >> txtfile, "\nEmpty entries:", numempty numempty = 0 print >> txtfile, "Hash (hex):", for j in xrange(20): print >> txtfile, hex(ord(entry[j])), (j, ) = struct.unpack(">L", entry[20:24]) print >> txtfile, "\nEntry id:", hex(j) else: numempty += 1 print >> txtfile, "\nTrailing data (hex):", for i in buf[len(buf) - (len(buf) % 24):]: print >> txtfile, hex(ord(i)), print >> txtfile txtfile.close() ################################################################################ def handle_live_pirs(infile, fsize): """LIVE and PIRS files are archive files. They contain a certificate, payload, SHA1 checksums, 2 icons, textual information, and the files themselves. @param infile pointer to the archive file @param fsize size of infile """ print "Handling LIVE/PIRS file." if not check_size(fsize, 0xD000): return txtfile = open_info_file(infile) if txtfile != None: print >> txtfile, "Certificate (hex):", cert = infile.read(0x100) for i in cert: print >> txtfile, hex(ord(i)), print >> txtfile, "\n\nData (hex):", data = infile.read(0x228) for i in data: print >> txtfile, hex(ord(i)), print >> txtfile ### BEGIN wxPirs ### infile.seek(0xC032) # originally 4 bytes at 0xC030 (pathind, ) = struct.unpack(">H", infile.read(2)) if pathind == 0xFFFF: start = 0xC000 else: start = 0xD000 ### END wxPirs ### write_common_part(infile, txtfile, 0xB000, start) ################################################################################ # End of code taken from extract360.py. def getFileOrURL(filename, url): # Check if a file named filename exists on disk. # If so, return its contents. If not, download it, save it, and return its contents. try: f = open(filename) print "Found", filename, "cached on disk, using local copy" retval = f.read() return retval except IOError, e: pass print "Downloading", filename, "from", url req = Request(url) try: response = urlopen(req) except URLError, e: if hasattr(e, 'reason'): print "Failed to reach download server. Reason:", e.reason elif hasattr(e, 'code'): print "The server couldn't fulfill the request. Error code:", e.code print "Reading response..." retval = response.read() # Save downloaded file to disk f = open(filename, "wb") f.write(retval) f.close() print "done, saved to", filename return retval def extractPirsFromZip(systemupdate): print "Extracting $SystemUpdate/FFFE07DF00000001 from system update file..." updatefile = StringIO.StringIO(systemupdate) z = zipfile.ZipFile(updatefile) #print z.namelist() pirs = z.open("$SystemUpdate/FFFE07DF00000001").read() print "done." return pirs if __name__ == "__main__": target = "audios.bin" if len(sys.argv) == 2: target = sys.argv[1] if not os.path.isfile(target): fw = getFileOrURL("SystemUpdate.zip", "http://www.xbox.com/system-update-usb") pirs = extractPirsFromZip(fw) lang = ["English", "Japanese", "German", "French", "Spanish", "Italian", "Korean", "Chinese", "Portuguese"] sio = StringIO.StringIO(pirs) basename = "FFFE07DF00000001" sio.name = basename pwd = os.getcwd() handle_live_pirs(sio, len(pirs)-4) os.chdir(pwd) print "Moving audios.bin to current folder" os.rename(os.path.join(basename + ".dir", "audios.bin"), target) print "Cleaning up" os.unlink(basename + ".txt") for root, dirs, files in os.walk(basename + ".dir"): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) os.rmdir(root) os.unlink("SystemUpdate.zip") print "Done!" else: print "Already have audios.bin" libfreenect-0.5.3/src/libfreenect.pc.in000066400000000000000000000005421264163024100200030ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${exec_prefix}/@PROJECT_LIBRARY_INSTALL_DIR@ includedir=${prefix}/@PROJECT_INCLUDE_INSTALL_DIR@ Name: @CMAKE_PROJECT_NAME@ Description: Interface to the Microsoft Kinect sensor device. Requires.private: libusb-1.0 Version: @PROJECT_APIVER@ Libs: -L${libdir} -lfreenect Cflags: -I${includedir} libfreenect-0.5.3/src/loader.c000066400000000000000000000326401264163024100162060ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "freenect_internal.h" #include "loader.h" #include #include #include #include static void dump_bl_cmd(freenect_context* ctx, bootloader_command cmd) { int i; for(i = 0; i < 24; i++) FN_INFO("%02X ", ((unsigned char*)(&cmd))[i]); FN_INFO("\n"); } static void dump_cemd_cmd(freenect_context* ctx, cemdloader_command cmd) { int i; for(i = 0; i < 24; i++) FN_INFO("%02X ", ((unsigned char*)(&cmd))[i]); FN_INFO("(%d more zeros)\n", (int)(sizeof(cmd)-24)); } static int get_reply(fnusb_dev* dev) { freenect_context* ctx = dev->parent->parent; unsigned char dump[512]; bootloader_status_code buffer; int res; int transferred; res = fnusb_bulk(dev, 0x81, dump, 512, &transferred); if(res != 0 || transferred != sizeof(bootloader_status_code)) { FN_ERROR("Error reading reply: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)(sizeof(bootloader_status_code))); return res; } memcpy(&buffer, dump, sizeof(bootloader_status_code)); if(fn_le32(buffer.magic) != 0x0a6fe000) { FN_ERROR("Error reading reply: invalid magic %08X\n",buffer.magic); return -1; } if(fn_le32(buffer.tag) != dev->parent->audio_tag) { FN_ERROR("Error reading reply: non-matching tag number %08X (expected %08X)\n", buffer.tag, dev->parent->audio_tag); return -1; } if(fn_le32(buffer.status) != 0) { FN_ERROR("Notice reading reply: last uint32_t was nonzero: %d\n", buffer.status); } FN_INFO("Reading reply: "); int i; for(i = 0; i < transferred; ++i) { FN_INFO("%02X ", ((unsigned char*)(&buffer))[i]); } FN_INFO("\n"); return res; } static int check_version_string(fnusb_dev* dev) { freenect_context* ctx = dev->parent->parent; bootloader_command bootcmd; memset(&bootcmd, 0, sizeof(bootcmd)); bootcmd.magic = fn_le32(0x06022009); bootcmd.tag = fn_le32(dev->parent->audio_tag); bootcmd.bytes = fn_le32(0x60); bootcmd.cmd = fn_le32(0); bootcmd.addr = fn_le32(0x15); unsigned char buffer[512]; int res; int transferred; FN_INFO("check_version_string(): About to send: "); dump_bl_cmd(ctx, bootcmd); // Send "get version string" command res = fnusb_bulk(dev, 1, (unsigned char*)&bootcmd, sizeof(bootcmd), &transferred); if(res != 0 || transferred != sizeof(bootcmd)) { FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, (int)sizeof(bootcmd)); return -1; } // Read version string reply res = fnusb_bulk(dev, 0x81, buffer, 512, &transferred); if(res != 0 ) { FN_ERROR("Error reading version string: %d\ttransferred: %d (expected %d)\n", res, transferred, 0x60); return res; } FN_INFO("Read version string: "); int i; for(i = 0; i < transferred; ++i) { FN_INFO("%02X ", buffer[i]); } FN_INFO("\n"); // Read status code reply res = get_reply(dev); dev->parent->audio_tag++; return res; } FN_INTERNAL int upload_firmware(fnusb_dev* dev, char * filename) { freenect_context* ctx = dev->parent->parent; /* Search for firmware file (audios.bin) in the following places: * $LIBFREENECT_FIRMWARE_PATH * . * ${HOME}/.libfreenect * /usr/local/share/libfreenect * /usr/share/libfreenect * ./../Resources/ ( for OS X ) */ //need to add a forward slash char fw_filename[1024]; sprintf(fw_filename, "/%s", filename); int filenamelen = strlen(fw_filename); int i; int searchpathcount; FILE* fw = NULL; for(i = 0, searchpathcount = 6; !fw && i < searchpathcount; i++) { char* fwfile; int needs_free = 0; switch(i) { case 0: { char* envpath = getenv("LIBFREENECT_FIRMWARE_PATH"); if (!envpath) continue; int pathlen = strlen(envpath); fwfile = (char *)malloc(pathlen + filenamelen + 1); strcpy(fwfile, envpath); strcat(fwfile, fw_filename); needs_free = 1; } break; case 1: //fwfile = "./audios.bin"; fwfile = (char *)malloc(2048); needs_free = 1; sprintf(fwfile, ".%s", fw_filename); break; case 2: { // Construct $HOME/.libfreenect/ char* home = getenv("HOME"); if (!home) continue; int homelen = strlen(home); char* dotfolder = "/.libfreenect"; int locallen = strlen(dotfolder); fwfile = (char*)malloc(homelen + locallen + filenamelen + 1); strcpy(fwfile, home); strcat(fwfile, dotfolder); strcat(fwfile, fw_filename); needs_free = 1; } break; case 3: //fwfile = "/usr/local/share/libfreenect/audios.bin"; fwfile = (char *)malloc(2048); needs_free = 1; sprintf(fwfile, "/usr/local/share/libfreenect%s", fw_filename); break; case 4: //fwfile = "/usr/share/libfreenect/audios.bin"; fwfile = (char *)malloc(2048); needs_free = 1; sprintf(fwfile, "/usr/share/libfreenect%s", fw_filename); break; case 5: //fwfile = "./../Resources/audios.bin"; //default for OS X equivilant to: "./audios.bin"; fwfile = (char *)malloc(2048); needs_free = 1; sprintf(fwfile, "./../Resources%s", fw_filename); break; default: break; } FN_INFO("Trying to open %s as firmware...\n", fwfile); fw = fopen(fwfile, "rb"); if (needs_free) { free(fwfile); } } if (!fw) { FN_ERROR("upload_firmware: failed to find firmware file.\n"); return -errno; } // get the number of bytes of the file fseek(fw , 0, SEEK_END); int fw_num_bytes = ftell(fw); rewind(fw); if( fw_num_bytes <= 0 ){ FN_ERROR("upload_firmware: failed to find file with any data.\n"); return -errno; } unsigned char * fw_bytes = (unsigned char *)malloc(fw_num_bytes); int numRead = fread(fw_bytes, 1, fw_num_bytes, fw); fw_num_bytes = numRead; // just in case int retVal = upload_firmware_from_memory(dev, fw_bytes, fw_num_bytes); fclose(fw); fw = NULL; return retVal; } FN_INTERNAL int upload_firmware_from_memory(fnusb_dev* dev, unsigned char * fw_from_mem, unsigned int fw_size_in_btyes) { freenect_context* ctx = dev->parent->parent; bootloader_command bootcmd; memset(&bootcmd, 0, sizeof(bootcmd)); bootcmd.magic = fn_le32(0x06022009); int res; int transferred; firmware_header fwheader; int read = 0; int bytesLeft = fw_size_in_btyes; unsigned char * readPtr = &fw_from_mem[0]; if (fw_size_in_btyes < sizeof(firmware_header)) { FN_ERROR("upload_firmware: firmware image too small, has no header?\n"); return -errno; } memcpy(&fwheader, readPtr, sizeof(firmware_header)); // The file is serialized as little endian. fwheader.magic = fn_le32(fwheader.magic); fwheader.ver_major = fn_le16(fwheader.ver_major); fwheader.ver_minor = fn_le16(fwheader.ver_minor); fwheader.ver_release = fn_le16(fwheader.ver_release); fwheader.ver_patch = fn_le16(fwheader.ver_patch); fwheader.base_addr = fn_le32(fwheader.base_addr); fwheader.size = fn_le32(fwheader.size); fwheader.entry_addr = fn_le32(fwheader.entry_addr); FN_INFO("Found firmware image:\n"); FN_INFO("\tmagic %08X\n", fwheader.magic); FN_INFO("\tversion %02d.%02d.%02d.%02d\n", fwheader.ver_major, fwheader.ver_minor, fwheader.ver_release, fwheader.ver_patch); FN_INFO("\tbase address 0x%08x\n", fwheader.base_addr); FN_INFO("\tsize 0x%08x\n", fwheader.size); FN_INFO("\tentry point 0x%08x\n", fwheader.entry_addr); uint32_t addr = fwheader.base_addr; unsigned char page[0x4000]; int readIndex = 0; int total_bytes_sent = 0; do { read = (0x4000 > fwheader.size - total_bytes_sent) ? fwheader.size - total_bytes_sent : 0x4000; // sanity check if( read > bytesLeft ){ read = bytesLeft; } if (read <= 0) { break; } memcpy(page, &readPtr[readIndex], read); readIndex += read; bytesLeft -= read; bootcmd.tag = fn_le32(dev->parent->audio_tag); bootcmd.bytes = fn_le32(read); bootcmd.cmd = fn_le32(0x03); bootcmd.addr = fn_le32(addr); FN_INFO("About to send: "); dump_bl_cmd(ctx, bootcmd); // Send it off! res = fnusb_bulk(dev, 1, (unsigned char*)&bootcmd, sizeof(bootcmd), &transferred); if(res != 0 || transferred != sizeof(bootcmd)) { FN_ERROR("upload_firmware(): Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, (int)(sizeof(bootcmd))); return -1; } int bytes_sent = 0; while(bytes_sent < read) { int to_send = (read - bytes_sent > 512 ? 512 : read - bytes_sent); res = fnusb_bulk(dev, 1, &page[bytes_sent], to_send, &transferred); if(res != 0 || transferred != to_send) { FN_ERROR("upload_firmware(): Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, to_send); return -1; } bytes_sent += to_send; total_bytes_sent += to_send; } res = get_reply(dev); addr += (uint32_t)read; dev->parent->audio_tag++; } while (read > 0); if (total_bytes_sent != fwheader.size) { FN_ERROR("upload_firmware: firmware image declared %d bytes, but file only contained %d bytes\n", fwheader.size, total_bytes_sent); return -1; } bootcmd.tag = fn_le32(dev->parent->audio_tag); bootcmd.bytes = fn_le32(0); bootcmd.cmd = fn_le32(0x04); bootcmd.addr = fn_le32(fwheader.entry_addr); dump_bl_cmd(ctx, bootcmd); res = fnusb_bulk(dev, 1, (unsigned char*)&bootcmd, sizeof(bootcmd), &transferred); if(res != 0 || transferred != sizeof(bootcmd)) { FN_ERROR("upload_firmware(): Error: res: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)sizeof(bootcmd)); return -1; } res = get_reply(dev); dev->parent->audio_tag++; FN_INFO("Firmware successfully uploaded and launched. Device will disconnect and reenumerate.\n"); return 0; } FN_INTERNAL int upload_cemd_data(fnusb_dev* dev) { // Now we upload the CEMD data. freenect_context* ctx = dev->parent->parent; cemdloader_command cemdcmd; memset(&cemdcmd, 0, sizeof(cemdcmd)); cemdcmd.magic = fn_le32(0x06022009); cemdcmd.tag = fn_le32(dev->parent->audio_tag); cemdcmd.arg1 = fn_le32(0); cemdcmd.cmd = fn_le32(0x00000133); cemdcmd.arg2 = fn_le32(0x00064014); // This is the length of the CEMD data. FN_INFO("Starting CEMD data upload:\n"); int res; int transferred; res = fnusb_bulk(dev, 1, (unsigned char*)&cemdcmd, sizeof(cemdcmd), &transferred); if(res != 0 || transferred != sizeof(cemdcmd)) { FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)sizeof(cemdcmd)); return -1; } res = get_reply(dev); dev->parent->audio_tag++; const char* cemd_filename = "cemd_data.bin"; FILE* cf = fopen(cemd_filename, "r"); if(cf == NULL) { FN_ERROR("upload_cemd_data: Failed to open %s: error %d", cemd_filename, errno); return errno; } uint32_t addr = 0x00000000; int read = 0; unsigned char page[0x4000]; do { read = fread(page, 1, 0x4000, cf); if(read <= 0) { break; } //LOG(""); cemdcmd.tag = fn_le32(dev->parent->audio_tag); cemdcmd.arg1 = fn_le32(read); cemdcmd.cmd = fn_le32(0x134); cemdcmd.arg2 = fn_le32(addr); FN_INFO("About to send: "); dump_cemd_cmd(ctx, cemdcmd); // Send it off! res = fnusb_bulk(dev, 1, (unsigned char*)&cemdcmd, sizeof(cemdcmd), &transferred); if(res != 0 || transferred != sizeof(cemdcmd)) { FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, (int)sizeof(cemdcmd)); return -1; } int bytes_sent = 0; while(bytes_sent < read) { int to_send = (read - bytes_sent > 512 ? 512 : read - bytes_sent); res = fnusb_bulk(dev, 1, &page[bytes_sent], to_send, &transferred); if(res != 0 || transferred != to_send) { FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, to_send); return -1; } bytes_sent += to_send; } res = get_reply(dev); addr += (uint32_t)read; dev->parent->audio_tag++; } while (read > 0); fclose(cf); cf = NULL; cemdcmd.tag = fn_le32(dev->parent->audio_tag); cemdcmd.arg1 = fn_le32(0); // bytes = 0 cemdcmd.cmd = fn_le32(0x135); cemdcmd.arg2 = fn_le32(0x00064000); // mimicing the USB logs. This is the # of bytes of actual CEMD data after the 20-byte CEMD header. FN_INFO("Finishing CEMD data upload...\n"); res = fnusb_bulk(dev, 1, (unsigned char*)&cemdcmd, sizeof(cemdcmd), &transferred); if(res != 0 || transferred != sizeof(cemdcmd)) { FN_ERROR("upload_cemd_data(): Error: res: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)sizeof(cemdcmd)); return -1; } res = get_reply(dev); dev->parent->audio_tag++; FN_INFO("CEMD data uploaded successfully.\n"); return 0; } libfreenect-0.5.3/src/loader.h000066400000000000000000000045471264163024100162200ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include #include "usb_libusb10.h" typedef struct { uint32_t magic; uint32_t tag; uint32_t bytes; uint32_t cmd; uint32_t addr; uint32_t unk; } bootloader_command; typedef struct { uint32_t magic; // Magic bytes. 2BL uses 0xF00BACCA, audios uses 0xCA77F00D uint16_t ver_minor; // The version string has four parts, each a 16-bit little-endian int. uint16_t ver_major; // Yes, minor comes before major. uint16_t ver_release; // uint16_t ver_patch; // uint32_t base_addr; // Base address of firmware image. 2BL starts at 0x10000, audios starts at 0x80000. uint32_t size; // Size of firmware image, in bytes uint32_t entry_addr; // Code entry point (absolute address) } firmware_header; typedef struct { uint32_t magic; uint32_t tag; uint32_t arg1; // initial command: 0. Firmware blocks: byte count. uint32_t cmd; uint32_t arg2; // initial command: byte count. Firmware blocks: target address. uint32_t zeros[8]; } cemdloader_command; typedef struct { uint32_t magic; uint32_t tag; uint32_t status; } bootloader_status_code; int upload_firmware(fnusb_dev* dev, char * fw_filename); int upload_firmware_from_memory(fnusb_dev* dev, unsigned char * fw_from_mem, unsigned int fw_size_in_bytes); int upload_cemd_data(fnusb_dev* dev); libfreenect-0.5.3/src/registration.c000066400000000000000000000373031264163024100174530ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.h" #include "freenect_internal.h" #include "registration.h" #include #include #include #include #define REG_X_VAL_SCALE 256 // "fixed-point" precision for double -> int32_t conversion #define S2D_PIXEL_CONST 10 #define S2D_CONST_OFFSET 0.375 #define DEPTH_SENSOR_X_RES 1280 #define DEPTH_MIRROR_X 0 #define DEPTH_MAX_METRIC_VALUE FREENECT_DEPTH_MM_MAX_VALUE #define DEPTH_NO_MM_VALUE FREENECT_DEPTH_MM_NO_VALUE #define DEPTH_MAX_RAW_VALUE FREENECT_DEPTH_RAW_MAX_VALUE #define DEPTH_NO_RAW_VALUE FREENECT_DEPTH_RAW_NO_VALUE #define DEPTH_X_OFFSET 1 #define DEPTH_Y_OFFSET 1 #define DEPTH_X_RES 640 #define DEPTH_Y_RES 480 // try to fill single empty pixels AKA "salt-and-pepper noise" // disabled by default, noise removal better handled in later stages // #define DENSE_REGISTRATION /// fill the table of horizontal shift values for metric depth -> RGB conversion static void freenect_init_depth_to_rgb(int32_t* depth_to_rgb, freenect_zero_plane_info* zpi) { uint32_t i,x_scale = DEPTH_SENSOR_X_RES / DEPTH_X_RES; double pixel_size = 1.0 / (zpi->reference_pixel_size * x_scale * S2D_PIXEL_CONST); double pixels_between_rgb_and_ir_cmos = zpi->dcmos_rcmos_dist * pixel_size * S2D_PIXEL_CONST; double reference_distance_in_pixels = zpi->reference_distance * pixel_size * S2D_PIXEL_CONST; memset(depth_to_rgb, DEPTH_NO_MM_VALUE, DEPTH_MAX_METRIC_VALUE * sizeof(int32_t)); for (i = 0; i < DEPTH_MAX_METRIC_VALUE; i++) { double current_depth_in_pixels = i * pixel_size; depth_to_rgb[i] = (( pixels_between_rgb_and_ir_cmos * (current_depth_in_pixels - reference_distance_in_pixels) / current_depth_in_pixels) + S2D_CONST_OFFSET) * REG_X_VAL_SCALE; } } // unrolled inner loop of the 11-bit unpacker static inline void unpack_8_pixels(uint8_t *raw, uint16_t *frame) { uint16_t baseMask = 0x7FF; uint8_t r0 = *(raw+0); uint8_t r1 = *(raw+1); uint8_t r2 = *(raw+2); uint8_t r3 = *(raw+3); uint8_t r4 = *(raw+4); uint8_t r5 = *(raw+5); uint8_t r6 = *(raw+6); uint8_t r7 = *(raw+7); uint8_t r8 = *(raw+8); uint8_t r9 = *(raw+9); uint8_t r10 = *(raw+10); frame[0] = (r0<<3) | (r1>>5); frame[1] = ((r1<<6) | (r2>>2) ) & baseMask; frame[2] = ((r2<<9) | (r3<<1) | (r4>>7) ) & baseMask; frame[3] = ((r4<<4) | (r5>>4) ) & baseMask; frame[4] = ((r5<<7) | (r6>>1) ) & baseMask; frame[5] = ((r6<<10) | (r7<<2) | (r8>>6) ) & baseMask; frame[6] = ((r8<<5) | (r9>>3) ) & baseMask; frame[7] = ((r9<<8) | (r10) ) & baseMask; } // apply registration data to a single packed frame FN_INTERNAL int freenect_apply_registration(freenect_device* dev, uint8_t* input_packed, uint16_t* output_mm) { freenect_registration* reg = &(dev->registration); // set output buffer to zero using pointer-sized memory access (~ 30-40% faster than memset) size_t i, *wipe = (size_t*)output_mm; for (i = 0; i < DEPTH_X_RES * DEPTH_Y_RES * sizeof(uint16_t) / sizeof(size_t); i++) wipe[i] = DEPTH_NO_MM_VALUE; uint16_t unpack[8]; uint32_t target_offset = DEPTH_Y_RES * reg->reg_pad_info.start_lines; uint32_t x,y,source_index = 8; for (y = 0; y < DEPTH_Y_RES; y++) { for (x = 0; x < DEPTH_X_RES; x++) { // get 8 pixels from the packed frame if (source_index == 8) { unpack_8_pixels( input_packed, unpack ); source_index = 0; input_packed += 11; } // get the value at the current depth pixel, convert to millimeters uint16_t metric_depth = reg->raw_to_mm_shift[ unpack[source_index++] ]; // so long as the current pixel has a depth value if (metric_depth == DEPTH_NO_MM_VALUE) continue; if (metric_depth >= DEPTH_MAX_METRIC_VALUE) continue; // calculate the new x and y location for that pixel // using registration_table for the basic rectification // and depth_to_rgb_shift for determining the x shift uint32_t reg_index = DEPTH_MIRROR_X ? ((y + 1) * DEPTH_X_RES - x - 1) : (y * DEPTH_X_RES + x); uint32_t nx = (reg->registration_table[reg_index][0] + reg->depth_to_rgb_shift[metric_depth]) / REG_X_VAL_SCALE; uint32_t ny = reg->registration_table[reg_index][1]; // ignore anything outside the image bounds if (nx >= DEPTH_X_RES) continue; // convert nx, ny to an index in the depth image array uint32_t target_index = (DEPTH_MIRROR_X ? ((ny + 1) * DEPTH_X_RES - nx - 1) : (ny * DEPTH_X_RES + nx)) - target_offset; // get the current value at the new location uint16_t current_depth = output_mm[target_index]; // make sure the new location is empty, or the new value is closer if ((current_depth == DEPTH_NO_MM_VALUE) || (current_depth > metric_depth)) { output_mm[target_index] = metric_depth; // always save depth at current location #ifdef DENSE_REGISTRATION // if we're not on the first row, or the first column if ((nx > 0) && (ny > 0)) { output_mm[target_index - DEPTH_X_RES ] = metric_depth; // save depth at (x,y-1) output_mm[target_index - DEPTH_X_RES - 1] = metric_depth; // save depth at (x-1,y-1) output_mm[target_index - 1] = metric_depth; // save depth at (x-1,y) } else if (ny > 0) { output_mm[target_index - DEPTH_X_RES] = metric_depth; // save depth at (x,y-1) } else if (nx > 0) { output_mm[target_index - 1] = metric_depth; // save depth at (x-1,y) } #endif } } } return 0; } // Same as freenect_apply_registration, but don't bother aligning to the RGB image FN_INTERNAL int freenect_apply_depth_to_mm(freenect_device* dev, uint8_t* input_packed, uint16_t* output_mm) { freenect_registration* reg = &(dev->registration); uint16_t unpack[8]; uint32_t x,y,source_index = 8; for (y = 0; y < DEPTH_Y_RES; y++) { for (x = 0; x < DEPTH_X_RES; x++) { // get 8 pixels from the packed frame if (source_index == 8) { unpack_8_pixels( input_packed, unpack ); source_index = 0; input_packed += 11; } // get the value at the current depth pixel, convert to millimeters uint16_t metric_depth = reg->raw_to_mm_shift[ unpack[source_index++] ]; output_mm[y * DEPTH_X_RES + x] = metric_depth < DEPTH_MAX_METRIC_VALUE ? metric_depth : DEPTH_MAX_METRIC_VALUE; } } return 0; } // create temporary x/y shift tables static void freenect_create_dxdy_tables(double* reg_x_table, double* reg_y_table, int32_t resolution_x, int32_t resolution_y, freenect_reg_info* regdata ) { int64_t AX6 = regdata->ax; int64_t BX6 = regdata->bx; int64_t CX2 = regdata->cx; int64_t DX2 = regdata->dx; int64_t AY6 = regdata->ay; int64_t BY6 = regdata->by; int64_t CY2 = regdata->cy; int64_t DY2 = regdata->dy; // don't merge the shift operations - necessary for proper 32-bit clamping of extracted values int64_t dX0 = (regdata->dx_start << 13) >> 4; int64_t dY0 = (regdata->dy_start << 13) >> 4; int64_t dXdX0 = (regdata->dxdx_start << 11) >> 3; int64_t dXdY0 = (regdata->dxdy_start << 11) >> 3; int64_t dYdX0 = (regdata->dydx_start << 11) >> 3; int64_t dYdY0 = (regdata->dydy_start << 11) >> 3; int64_t dXdXdX0 = (regdata->dxdxdx_start << 5) << 3; int64_t dYdXdX0 = (regdata->dydxdx_start << 5) << 3; int64_t dYdXdY0 = (regdata->dydxdy_start << 5) << 3; int64_t dXdXdY0 = (regdata->dxdxdy_start << 5) << 3; int64_t dYdYdX0 = (regdata->dydydx_start << 5) << 3; int64_t dYdYdY0 = (regdata->dydydy_start << 5) << 3; int32_t row,col,tOffs = 0; for (row = 0 ; row < resolution_y ; row++) { dXdXdX0 += CX2; dXdX0 += dYdXdX0 >> 8; dYdXdX0 += DX2; dX0 += dYdX0 >> 6; dYdX0 += dYdYdX0 >> 8; dYdYdX0 += BX6; dXdXdY0 += CY2; dXdY0 += dYdXdY0 >> 8; dYdXdY0 += DY2; dY0 += dYdY0 >> 6; dYdY0 += dYdYdY0 >> 8; dYdYdY0 += BY6; int64_t coldXdXdY0 = dXdXdY0, coldXdY0 = dXdY0, coldY0 = dY0; int64_t coldXdXdX0 = dXdXdX0, coldXdX0 = dXdX0, coldX0 = dX0; for (col = 0 ; col < resolution_x ; col++, tOffs++) { reg_x_table[tOffs] = coldX0 * (1.0/(1<<17)); reg_y_table[tOffs] = coldY0 * (1.0/(1<<17)); coldX0 += coldXdX0 >> 6; coldXdX0 += coldXdXdX0 >> 8; coldXdXdX0 += AX6; coldY0 += coldXdY0 >> 6; coldXdY0 += coldXdXdY0 >> 8; coldXdXdY0 += AY6; } } } static void freenect_init_registration_table(int32_t (*registration_table)[2], freenect_reg_info* reg_info) { double* regtable_dx = (double*)malloc(DEPTH_X_RES*DEPTH_Y_RES*sizeof(double)); double* regtable_dy = (double*)malloc(DEPTH_X_RES*DEPTH_Y_RES*sizeof(double)); memset(regtable_dx, 0, DEPTH_X_RES*DEPTH_Y_RES * sizeof(double)); memset(regtable_dy, 0, DEPTH_X_RES*DEPTH_Y_RES * sizeof(double)); int32_t x,y,index = 0; // create temporary dx/dy tables freenect_create_dxdy_tables( regtable_dx, regtable_dy, DEPTH_X_RES, DEPTH_Y_RES, reg_info ); for (y = 0; y < DEPTH_Y_RES; y++) { for (x = 0; x < DEPTH_X_RES; x++, index++) { double new_x = x + regtable_dx[index] + DEPTH_X_OFFSET; double new_y = y + regtable_dy[index] + DEPTH_Y_OFFSET; if ((new_x < 0) || (new_y < 0) || (new_x >= DEPTH_X_RES) || (new_y >= DEPTH_Y_RES)) new_x = 2 * DEPTH_X_RES; // intentionally set value outside image bounds registration_table[index][0] = new_x * REG_X_VAL_SCALE; registration_table[index][1] = new_y; } } free(regtable_dx); free(regtable_dy); } // These are just constants. static double parameter_coefficient = 4; static double shift_scale = 10; static double pixel_size_factor = 1; /// convert raw shift value to metric depth (in mm) static uint16_t freenect_raw_to_mm(uint16_t raw, freenect_registration* reg) { freenect_zero_plane_info* zpi = &(reg->zero_plane_info); double fixed_ref_x = ((raw - (parameter_coefficient * reg->const_shift / pixel_size_factor)) / parameter_coefficient) - S2D_CONST_OFFSET; double metric = fixed_ref_x * zpi->reference_pixel_size * pixel_size_factor; return shift_scale * ((metric * zpi->reference_distance / (zpi->dcmos_emitter_dist - metric)) + zpi->reference_distance); } /// Compute registration tables. static void complete_tables(freenect_registration* reg) { uint16_t i; for (i = 0; i < DEPTH_MAX_RAW_VALUE; i++) reg->raw_to_mm_shift[i] = freenect_raw_to_mm( i, reg); reg->raw_to_mm_shift[DEPTH_NO_RAW_VALUE] = DEPTH_NO_MM_VALUE; freenect_init_depth_to_rgb( reg->depth_to_rgb_shift, &(reg->zero_plane_info) ); freenect_init_registration_table( reg->registration_table, &(reg->reg_info) ); } /// camera -> world coordinate helper function void freenect_camera_to_world(freenect_device* dev, int cx, int cy, int wz, double* wx, double* wy) { double ref_pix_size = dev->registration.zero_plane_info.reference_pixel_size; double ref_distance = dev->registration.zero_plane_info.reference_distance; // We multiply cx and cy by these factors because they come from a 640x480 image, // but the zero plane pixel size is for a 1280x1024 image. // However, the 640x480 image is produced by cropping the 1280x1024 image // to 1280x960 and then scaling by .5, so aspect ratio is maintained, and // we should simply multiply by two in each dimension. double factor = 2 * ref_pix_size * wz / ref_distance; *wx = (double)(cx - DEPTH_X_RES/2) * factor; *wy = (double)(cy - DEPTH_Y_RES/2) * factor; } /// RGB -> depth mapping function (inverse of default FREENECT_DEPTH_REGISTERED mapping) void freenect_map_rgb_to_depth(freenect_device* dev, uint16_t* depth_mm, uint8_t* rgb_raw, uint8_t* rgb_registered) { uint32_t target_offset = dev->registration.reg_pad_info.start_lines * DEPTH_Y_RES; int x,y; int* map = (int*)malloc(DEPTH_Y_RES*DEPTH_X_RES* sizeof(int)); unsigned short* zBuffer = (unsigned short*)malloc(DEPTH_Y_RES*DEPTH_X_RES* sizeof(unsigned short)); memset(zBuffer, DEPTH_NO_MM_VALUE, DEPTH_X_RES*DEPTH_Y_RES * sizeof(unsigned short)); for (y = 0; y < DEPTH_Y_RES; y++) for (x = 0; x < DEPTH_X_RES; x++) { uint32_t index = y * DEPTH_X_RES + x; uint32_t cx,cy,cindex; map[index] = -1; int wz = depth_mm[index]; if (wz == DEPTH_NO_MM_VALUE) { continue; } // coordinates in rgb image corresponding to x,y in depth image cx = (dev->registration.registration_table[index][0] + dev->registration.depth_to_rgb_shift[wz]) / REG_X_VAL_SCALE; cy = dev->registration.registration_table[index][1] - target_offset; if (cx >= DEPTH_X_RES) continue; cindex = cy*DEPTH_X_RES+cx; map[index] = cindex; if (zBuffer[cindex] == DEPTH_NO_MM_VALUE || zBuffer[cindex] > wz) { zBuffer[cindex] = wz; } } for (y = 0; y < DEPTH_Y_RES; y++) for (x = 0; x < DEPTH_X_RES; x++) { uint32_t index = y * DEPTH_X_RES + x; uint32_t cindex = map[index]; // pixels without depth data or out of bounds are black if (cindex == -1) { index *= 3; rgb_registered[index+0] = 0; rgb_registered[index+1] = 0; rgb_registered[index+2] = 0; continue; } unsigned short currentDepth = depth_mm[index]; unsigned short minDepth = zBuffer[cindex]; // filters out pixels that are occluded if (currentDepth <= minDepth) { index *= 3; cindex *= 3; rgb_registered[index+0] = rgb_raw[cindex+0]; rgb_registered[index+1] = rgb_raw[cindex+1]; rgb_registered[index+2] = rgb_raw[cindex+2]; } } free(zBuffer); free(map); } /// Allocate and fill registration tables /// This function should be called every time a new video (not depth!) mode is /// activated. FN_INTERNAL int freenect_init_registration(freenect_device* dev) { freenect_registration* reg = &(dev->registration); // Ensure that we free the previous tables before dropping the pointers, if there were any. freenect_destroy_registration(&(dev->registration)); // Allocate tables. reg->raw_to_mm_shift = (uint16_t*)malloc( sizeof(uint16_t) * DEPTH_MAX_RAW_VALUE ); reg->depth_to_rgb_shift = (int32_t*)malloc( sizeof( int32_t) * DEPTH_MAX_METRIC_VALUE ); reg->registration_table = (int32_t (*)[2])malloc( sizeof( int32_t) * DEPTH_X_RES * DEPTH_Y_RES * 2 ); // Fill tables. complete_tables(reg); return 0; } freenect_registration freenect_copy_registration(freenect_device* dev) { freenect_registration retval; retval.reg_info = dev->registration.reg_info; retval.reg_pad_info = dev->registration.reg_pad_info; retval.zero_plane_info = dev->registration.zero_plane_info; retval.const_shift = dev->registration.const_shift; retval.raw_to_mm_shift = (uint16_t*)malloc( sizeof(uint16_t) * DEPTH_MAX_RAW_VALUE ); retval.depth_to_rgb_shift = (int32_t*)malloc( sizeof( int32_t) * DEPTH_MAX_METRIC_VALUE ); retval.registration_table = (int32_t (*)[2])malloc( sizeof( int32_t) * DEPTH_X_RES * DEPTH_Y_RES * 2 ); complete_tables(&retval); return retval; } int freenect_destroy_registration(freenect_registration* reg) { if (reg->raw_to_mm_shift) { free(reg->raw_to_mm_shift); reg->raw_to_mm_shift = NULL; } if (reg->depth_to_rgb_shift) { free(reg->depth_to_rgb_shift); reg->depth_to_rgb_shift = NULL; } if (reg->registration_table) { free(reg->registration_table); reg->registration_table = NULL; } return 0; } libfreenect-0.5.3/src/registration.h000066400000000000000000000026521264163024100174570ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB * file for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" // Internal function declarations relating to registration int freenect_init_registration(freenect_device* dev); int freenect_apply_registration(freenect_device* dev, uint8_t* input_packed, uint16_t* output_mm); int freenect_apply_depth_to_mm(freenect_device* dev, uint8_t* input_packed, uint16_t* output_mm); libfreenect-0.5.3/src/tilt.c000066400000000000000000000233471264163024100157200ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include #include "freenect_internal.h" // The kinect can tilt from +31 to -31 degrees in what looks like 1 degree increments // The control input looks like 2*desired_degrees #define MAX_TILT_ANGLE 31 #define MIN_TILT_ANGLE (-31) #define GRAVITY 9.80665 // Structs for 1473 and K4W communication typedef struct { uint32_t magic; uint32_t tag; uint32_t arg1; uint32_t cmd; uint32_t arg2; }fn_alt_motor_command; typedef struct { uint32_t magic; uint32_t tag; uint32_t status; }fn_alt_motor_reply; static int tag_seq = 0; static int tag_next_ack = 0; int get_reply(libusb_device_handle* dev, freenect_context *ctx){ unsigned char buffer[512]; memset(buffer, 0, 512); int transferred = 0; int res = 0; res = libusb_bulk_transfer(dev, 0x81, buffer, 512, &transferred, 100); if (res != 0) { FN_ERROR("get_reply(): libusb_bulk_transfer failed: %d (transferred = %d)\n", res, transferred); } else if (transferred != 12) { FN_ERROR("get_reply(): weird - got %d bytes (expected 12)\n", transferred); } else { fn_alt_motor_reply reply; memcpy(&reply, buffer, sizeof(reply)); if (reply.magic != 0x0a6fe000) { FN_ERROR("Bad magic: %08X (expected 0A6FE000\n", reply.magic); res = -1; } //can't really do this as tag_seq is static. with two cameras this is not going to match. could put in as part of libusb_device but I don't think it really matters. // if (reply.tag != tag_next_ack) { // FN_ERROR("Reply tag out of order: expected %d, got %d\n", tag_next_ack, reply.tag); // res = -1; // } if (reply.status != 0) { FN_ERROR("reply status != 0: failure?\n"); res = -1; } tag_next_ack++; } return res; } freenect_raw_tilt_state* freenect_get_tilt_state(freenect_device *dev) { return &dev->raw_state; } int update_tilt_state_alt(freenect_device *dev) { freenect_context *ctx = dev->parent; if (dev->usb_audio.dev == NULL) { FN_WARNING("Motor control failed: audio device missing"); return -1; } int transferred = 0; int res = 0; fn_alt_motor_command cmd; cmd.magic = fn_le32(0x06022009); cmd.tag = fn_le32(tag_seq++); cmd.arg1 = fn_le32(0x68); // 104. Incidentally, the number of bytes that we expect in the reply. cmd.cmd = fn_le32(0x8032); unsigned char buffer[256]; memcpy(buffer, &cmd, 16); res = libusb_bulk_transfer(dev->usb_audio.dev, 0x01, buffer, 16, &transferred, 250); if (res != 0) { return res; } res = libusb_bulk_transfer(dev->usb_audio.dev, 0x81, buffer, 256, &transferred, 250); // 104 bytes if (res != 0) { return res; } struct { int32_t x; int32_t y; int32_t z; int32_t tilt; } accel_and_tilt; memcpy(&accel_and_tilt, buffer + 16, sizeof(accel_and_tilt)); FN_SPEW("Accelerometer state: X == %d \t Y == %d \t Z == %d \t Tilt == %d\n", accel_and_tilt.x, accel_and_tilt.y, accel_and_tilt.z, accel_and_tilt.tilt); dev->raw_state.accelerometer_x = (int16_t)accel_and_tilt.x; dev->raw_state.accelerometer_y = (int16_t)accel_and_tilt.y; dev->raw_state.accelerometer_z = (int16_t)accel_and_tilt.z; // this is multiplied by 2 as the older 1414 device reports angles doubled and freenect takes this into account dev->raw_state.tilt_angle = (int8_t)accel_and_tilt.tilt * 2; // Reply: skip four uint32_t, then you have three int32_t that give you acceleration in that direction, it seems. // Units still to be worked out. return get_reply(dev->usb_audio.dev, ctx); } int freenect_update_tilt_state(freenect_device *dev) { freenect_context *ctx = dev->parent; //if we have motor control via audio and fw is uploaded - call the alt function if( dev->motor_control_with_audio_enabled ){ return update_tilt_state_alt(dev); } if(!(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) return 0; uint8_t buf[10]; uint16_t ux, uy, uz; int ret = fnusb_control(&dev->usb_motor, 0xC0, 0x32, 0x0, 0x0, buf, 10); if (ret != 10) { FN_ERROR("Error in accelerometer reading, libusb_control_transfer returned %d\n", ret); return ret < 0 ? ret : -1; } ux = ((uint16_t)buf[2] << 8) | buf[3]; uy = ((uint16_t)buf[4] << 8) | buf[5]; uz = ((uint16_t)buf[6] << 8) | buf[7]; dev->raw_state.accelerometer_x = (int16_t)ux; dev->raw_state.accelerometer_y = (int16_t)uy; dev->raw_state.accelerometer_z = (int16_t)uz; dev->raw_state.tilt_angle = (int8_t)buf[8]; dev->raw_state.tilt_status = (freenect_tilt_status_code)buf[9]; return ret; } int freenect_set_tilt_degs_alt(freenect_device *dev, int tilt_degrees) { freenect_context *ctx = dev->parent; if (tilt_degrees > 31 || tilt_degrees < -31) { FN_WARNING("set_tilt(): degrees %d out of safe range [-31, 31]\n", tilt_degrees); return -1; } if (dev->usb_audio.dev == NULL) { FN_WARNING("Motor control failed: audio device missing"); return -1; } fn_alt_motor_command cmd; cmd.magic = fn_le32(0x06022009); cmd.tag = fn_le32(tag_seq++); cmd.arg1 = fn_le32(0); cmd.cmd = fn_le32(0x803b); cmd.arg2 = (uint32_t)(fn_le32((int32_t)tilt_degrees)); int transferred = 0; int res = 0; unsigned char buffer[20]; memcpy(buffer, &cmd, 20); res = libusb_bulk_transfer(dev->usb_audio.dev, 0x01, buffer, 20, &transferred, 250); if (res != 0) { FN_ERROR("freenect_set_tilt_alt(): libusb_bulk_transfer failed: %d (transferred = %d)\n", res, transferred); return res; } return get_reply(dev->usb_audio.dev, ctx); } int freenect_set_tilt_degs(freenect_device *dev, double angle) { freenect_context *ctx = dev->parent; //if we have motor control via audio and fw is uploaded - call the alt function if( dev->motor_control_with_audio_enabled ){ return freenect_set_tilt_degs_alt(dev, angle); } if(!(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) return 0; int ret; uint8_t empty[0x1]; angle = (angleMAX_TILT_ANGLE) ? MAX_TILT_ANGLE : angle); angle = angle * 2; ret = fnusb_control(&dev->usb_motor, 0x40, 0x31, (int16_t)angle, 0x0, empty, 0x0); return ret; } FN_INTERNAL int fnusb_set_led_alt(libusb_device_handle * dev, freenect_context * ctx, freenect_led_options state) { enum { LED_ALT_OFF = 1, LED_ALT_BLINK_GREEN = 2, LED_ALT_SOLID_GREEN = 3, LED_ALT_SOLID_RED = 4, }; //The LED states are different between K4W/1473 and older 1414 if( state == LED_GREEN ){ state = (freenect_led_options)LED_ALT_SOLID_GREEN; }else if( state == LED_RED ){ state = (freenect_led_options)LED_ALT_SOLID_RED; }else if( state == LED_YELLOW ){ state = (freenect_led_options)LED_ALT_SOLID_GREEN; }else if( state == LED_OFF ){ state = (freenect_led_options)LED_ALT_OFF; }else if( state == LED_BLINK_GREEN ){ state = (freenect_led_options)LED_ALT_BLINK_GREEN; }else{ state = LED_GREEN; } fn_alt_motor_command cmd; cmd.magic = fn_le32(0x06022009); cmd.tag = fn_le32(tag_seq++); cmd.arg1 = fn_le32(0); cmd.cmd = fn_le32(0x10); cmd.arg2 = (uint32_t)(fn_le32((int32_t)state)); unsigned char buffer[20]; memcpy(buffer, &cmd, 20); int transferred = 0; int res = libusb_bulk_transfer(dev, 0x01, buffer, 20, &transferred, 100); if (res != 0) { FN_WARNING("fnusb_set_led_alt(): libusb_bulk_transfer failed: %d (transferred = %d)\n", res, transferred); return res; } return get_reply(dev, ctx); } int freenect_set_led_alt(freenect_device *dev, freenect_led_options state) { freenect_context *ctx = dev->parent; if (dev->usb_audio.dev == NULL) { FN_WARNING("Motor control failed: audio device missing"); return -1; } return fnusb_set_led_alt(dev->usb_audio.dev, ctx, state); } int freenect_set_led(freenect_device *dev, freenect_led_options option) { freenect_context *ctx = dev->parent; //if we have motor control via audio and fw is uploaded - call the alt function if( dev->motor_control_with_audio_enabled ){ return freenect_set_led_alt(dev, option); } if(!(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) return 0; int ret; uint8_t empty[0x1]; ret = fnusb_control(&dev->usb_motor, 0x40, 0x06, (uint16_t)option, 0x0, empty, 0x0); return ret; } double freenect_get_tilt_degs(freenect_raw_tilt_state *state) { return ((double)state->tilt_angle) / 2.; } freenect_tilt_status_code freenect_get_tilt_status(freenect_raw_tilt_state *state) { return state->tilt_status; } void freenect_get_mks_accel(freenect_raw_tilt_state *state, double* x, double* y, double* z) { //the documentation for the accelerometer (http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf) //states there are 819 counts/g *x = (double)state->accelerometer_x/FREENECT_COUNTS_PER_G*GRAVITY; *y = (double)state->accelerometer_y/FREENECT_COUNTS_PER_G*GRAVITY; *z = (double)state->accelerometer_z/FREENECT_COUNTS_PER_G*GRAVITY; } libfreenect-0.5.3/src/usb_libusb10.c000066400000000000000000000632001264163024100172260ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include #include "freenect_internal.h" #include "loader.h" #ifdef _MSC_VER # define sleep(x) Sleep((x)*1000) #endif FN_INTERNAL int fnusb_num_devices(fnusb_ctx *ctx) { libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices ssize_t cnt = libusb_get_device_list (ctx->ctx, &devs); //get the list of devices if (cnt < 0) return (-1); int nr = 0, i = 0; struct libusb_device_descriptor desc; for (i = 0; i < cnt; ++i) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor == VID_MICROSOFT && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) nr++; } libusb_free_device_list (devs, 1); // free the list, unref the devices in it return nr; } // Returns 1 if `pid` identifies K4W audio, 0 otherwise FN_INTERNAL int fnusb_is_pid_k4w_audio(int pid) { return (pid == PID_K4W_AUDIO || pid == PID_K4W_AUDIO_ALT_1 || pid == PID_K4W_AUDIO_ALT_2); } FN_INTERNAL libusb_device * fnusb_find_connected_audio_device(libusb_device * camera, libusb_device ** deviceList, int cnt) { if (cnt <= 0) return NULL; int cameraBusNo = libusb_get_bus_number(camera); if (cameraBusNo < 0) return NULL; libusb_device * cameraParent = libusb_get_parent(camera); int i = 0; for (i = 0; i < cnt; i++) { struct libusb_device_descriptor desc; int res = libusb_get_device_descriptor (deviceList[i], &desc); if (res < 0) { continue; } if (desc.idVendor == VID_MICROSOFT) { // make sure its some type of Kinect audio device if ((desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { int audioBusNo = libusb_get_bus_number(deviceList[i]); if (audioBusNo == cameraBusNo) { // we have a match! // let's double check libusb_device * audioParent = libusb_get_parent(deviceList[i]); if (cameraParent == audioParent) { return deviceList[i]; } } } } } return NULL; } FN_INTERNAL int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_device_attributes** attribute_list) { // todo: figure out how to log without freenect_context *attribute_list = NULL; // initialize some return value in case the user is careless. libusb_device **devs; // pointer to pointer of device, used to retrieve a list of devices ssize_t count = libusb_get_device_list (ctx->ctx, &devs); if (count < 0) { return -1; } struct freenect_device_attributes** next_attr = attribute_list; // Pass over the list. For each camera seen, if we already have a camera // for the newest_camera device, allocate a new one and append it to the list, // incrementing num_cams. int num_cams = 0; int i; for (i = 0; i < count; i++) { libusb_device* camera_device = devs[i]; struct libusb_device_descriptor desc; int res = libusb_get_device_descriptor (camera_device, &desc); if (res < 0) { continue; } if (desc.idVendor == VID_MICROSOFT && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // Verify that a serial number exists to query. If not, don't touch the device. if (desc.iSerialNumber == 0) { continue; } libusb_device_handle *camera_handle; res = libusb_open(camera_device, &camera_handle); if (res != 0) { continue; } // Read string descriptor referring to serial number. unsigned char serial[256]; // String descriptors are at most 256 bytes. res = libusb_get_string_descriptor_ascii(camera_handle, desc.iSerialNumber, serial, 256); libusb_close(camera_handle); if (res < 0) { continue; } // K4W and 1473 don't provide a camera serial; use audio serial instead. const char* const K4W_1473_SERIAL = "0000000000000000"; if (strncmp((const char*)serial, K4W_1473_SERIAL, 16) == 0) { libusb_device* audio_device = fnusb_find_connected_audio_device(camera_device, devs, count); if (audio_device != NULL) { struct libusb_device_descriptor audio_desc; res = libusb_get_device_descriptor(audio_device, &audio_desc); if (res != 0) { //FN_ERROR("Failed to get audio serial descriptors of K4W or 1473 device: %d\n", res); } else { libusb_device_handle * audio_handle = NULL; res = libusb_open(audio_device, &audio_handle); if (res != 0) { //FN_ERROR("Failed to open audio device for serial of K4W or 1473 device: %d\n", res); } else { res = libusb_get_string_descriptor_ascii(audio_handle, audio_desc.iSerialNumber, serial, 256); libusb_close(audio_handle); if (res != 0) { //FN_ERROR("Failed to get audio serial of K4W or 1473 device: %d\n", res); } } } } } // Add item to linked list. struct freenect_device_attributes* current_attr = (struct freenect_device_attributes*)malloc(sizeof(struct freenect_device_attributes)); memset(current_attr, 0, sizeof(*current_attr)); current_attr->camera_serial = strdup((char*)serial); *next_attr = current_attr; next_attr = &(current_attr->next); num_cams++; } } libusb_free_device_list(devs, 1); return num_cams; } FN_INTERNAL int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx) { int res; if (!usb_ctx) { res = libusb_init(&ctx->ctx); if (res >= 0) { ctx->should_free_ctx = 1; return 0; } else { ctx->should_free_ctx = 0; ctx->ctx = NULL; return res; } } else { // explicit cast required: in WIN32, freenect_usb_context* maps to void* ctx->ctx = (libusb_context*)usb_ctx; ctx->should_free_ctx = 0; return 0; } } FN_INTERNAL int fnusb_shutdown(fnusb_ctx *ctx) { //int res; if (ctx->should_free_ctx) { libusb_exit(ctx->ctx); ctx->ctx = NULL; } return 0; } FN_INTERNAL int fnusb_process_events(fnusb_ctx *ctx) { return libusb_handle_events(ctx->ctx); } FN_INTERNAL int fnusb_process_events_timeout(fnusb_ctx *ctx, struct timeval* timeout) { return libusb_handle_events_timeout(ctx->ctx, timeout); } int fnusb_claim_camera(freenect_device* dev) { freenect_context *ctx = dev->parent; int ret = 0; #ifndef _WIN32 // todo: necessary? // Detach an existing kernel driver for the device ret = libusb_kernel_driver_active(dev->usb_cam.dev, 0); if (ret == 1) { ret = libusb_detach_kernel_driver(dev->usb_cam.dev, 0); if (ret < 0) { FN_ERROR("Failed to detach camera kernel driver: %s\n", libusb_error_name(ret)); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; return ret; } } #endif ret = libusb_claim_interface(dev->usb_cam.dev, 0); if (ret < 0) { FN_ERROR("Failed to claim camera interface: %s\n", libusb_error_name(ret)); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; return ret; } if (dev->usb_cam.PID == PID_K4W_CAMERA) { ret = libusb_set_interface_alt_setting(dev->usb_cam.dev, 0, 1); if (ret != 0) { FN_ERROR("Failed to set alternate interface #1 for K4W: %s\n", libusb_error_name(ret)); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; return ret; } } return ret; } FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) { freenect_context *ctx = dev->parent; dev->device_does_motor_control_with_audio = 0; dev->motor_control_with_audio_enabled = 0; dev->usb_cam.parent = dev; dev->usb_cam.dev = NULL; dev->usb_motor.parent = dev; dev->usb_motor.dev = NULL; dev->usb_audio.parent = dev; dev->usb_audio.dev = NULL; libusb_device **devs; // pointer to pointer of device, used to retrieve a list of devices ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs); //get the list of devices if (cnt < 0) return -1; int i = 0, nr_cam = 0, nr_mot = 0; int nr_audio = 0; int res; struct libusb_device_descriptor desc; for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; res = 0; // Search for the camera if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // If the index given by the user matches our camera index if (nr_cam == index) { dev->usb_cam.VID = desc.idVendor; dev->usb_cam.PID = desc.idProduct; res = libusb_open (devs[i], &dev->usb_cam.dev); if (res < 0 || !dev->usb_cam.dev) { FN_ERROR("Could not open camera: %d\n", res); dev->usb_cam.dev = NULL; break; } if (desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267)) { freenect_device_flags requested_devices = ctx->enabled_subdevices; // Not the 1414 kinect so remove the motor flag, this should preserve the audio flag if set ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices & ~FREENECT_DEVICE_MOTOR); ctx->zero_plane_res = 334; dev->device_does_motor_control_with_audio = 1; // set the LED for non 1414 devices to keep the camera alive for some systems which get freezes libusb_device * audioDevice = fnusb_find_connected_audio_device(devs[i], devs, cnt); if (audioDevice != NULL) { libusb_device_handle * audioHandle = NULL; res = libusb_open(audioDevice, &audioHandle); if (res != 0) { FN_ERROR("Failed to set the LED of K4W or 1473 device: %d\n", res); } else { // we need to do this as it is possible that the device was not closed properly in a previous session // if we don't do this and the device wasn't closed properly - it can cause infinite hangs on LED and TILT functions libusb_reset_device(audioHandle); libusb_close(audioHandle); res = libusb_open(audioDevice, &audioHandle); if (res == 0) { res = libusb_claim_interface(audioHandle, 0); if (res != 0) { FN_ERROR("Unable to claim interface %d\n", res); } else { fnusb_set_led_alt(audioHandle, ctx, LED_GREEN); libusb_release_interface(audioHandle, 0); } libusb_close(audioHandle); } } } // for newer devices we need to enable the audio device for motor control // we only do this though if motor has been requested. if ((requested_devices & FREENECT_DEVICE_MOTOR) && (requested_devices & FREENECT_DEVICE_AUDIO) == 0) { ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices | FREENECT_DEVICE_AUDIO); } } else { // The good old kinect that tilts and tweets ctx->zero_plane_res = 322; } res = fnusb_claim_camera(dev); if (res < 0) { break; } } else { nr_cam++; } } } if (ctx->enabled_subdevices == FREENECT_DEVICE_CAMERA || res < 0) cnt = 0; // Search for the motor for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) { // If the index given by the user matches our camera index if (nr_mot == index) { dev->usb_motor.VID = desc.idVendor; dev->usb_motor.PID = desc.idProduct; res = libusb_open (devs[i], &dev->usb_motor.dev); if (res < 0 || !dev->usb_motor.dev) { FN_ERROR("Could not open motor: %d\n", res); dev->usb_motor.dev = NULL; break; } res = libusb_claim_interface (dev->usb_motor.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on motor: %d\n", res); libusb_close(dev->usb_motor.dev); dev->usb_motor.dev = NULL; break; } } else { nr_mot++; } } // Search for the audio if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { // If the index given by the user matches our audio index if (nr_audio == index) { dev->usb_audio.VID = desc.idVendor; dev->usb_audio.PID = desc.idProduct; res = libusb_open (devs[i], &dev->usb_audio.dev); if (res < 0 || !dev->usb_audio.dev) { FN_ERROR("Could not open audio: %d\n", res); dev->usb_audio.dev = NULL; break; } res = libusb_claim_interface (dev->usb_audio.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on audio: %d\n", res); libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; break; } // Using the device handle that we've claimed, see if this // device has already uploaded firmware (has 2 interfaces). // If not, save the serial number (by reading the appropriate // descriptor), upload the firmware, and then enter a loop // waiting for a device with the same serial number to // reappear. int num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if (num_interfaces >= 2) { if (dev->device_does_motor_control_with_audio) { dev->motor_control_with_audio_enabled = 1; } } else { // Read the serial number from the string descriptor and save it. unsigned char string_desc[256]; // String descriptors are at most 256 bytes res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256); if (res < 0) { FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n"); break; } char* audio_serial = strdup((char*)string_desc); FN_SPEW("Uploading firmware to audio device in bootloader state.\n"); // Check if we can load from memory - otherwise load from disk if (desc.idProduct == PID_NUI_AUDIO && ctx->fn_fw_nui_ptr && ctx->fn_fw_nui_size > 0) { FN_SPEW("loading firmware from memory\n"); res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_nui_ptr, ctx->fn_fw_nui_size); } else if (desc.idProduct == PID_K4W_AUDIO && ctx->fn_fw_k4w_ptr && ctx->fn_fw_k4w_size > 0) { FN_SPEW("loading firmware from memory\n"); res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_k4w_ptr, ctx->fn_fw_k4w_size); } else { res = upload_firmware(&dev->usb_audio, "audios.bin"); } if (res < 0) { FN_ERROR("upload_firmware failed: %d\n", res); break; } libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; // Wait for the device to reappear. int loops = 0; for (loops = 0; loops < 10; loops++) { FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial); // Scan devices. libusb_device **new_dev_list; int dev_index; ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list); for (dev_index = 0; dev_index < num_new_devs; ++dev_index) { struct libusb_device_descriptor new_dev_desc; int r; r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc); if (r < 0) continue; // If this dev is a Kinect audio device, open device, read serial, and compare. if (new_dev_desc.idVendor == VID_MICROSOFT && (new_dev_desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { FN_SPEW("Matched VID/PID!\n"); libusb_device_handle* new_dev_handle; // Open device r = libusb_open(new_dev_list[dev_index], &new_dev_handle); if (r < 0) continue; // Read serial r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256); if (r < 0) { FN_SPEW("Lost new audio device while fetching serial number.\n"); libusb_close(new_dev_handle); continue; } // Compare to expected serial if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) { // We found it! r = libusb_claim_interface(new_dev_handle, 0); if (r != 0) { // Ouch, found the device but couldn't claim the interface. FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial); libusb_close(new_dev_handle); continue; } // Save the device handle. dev->usb_audio.dev = new_dev_handle; // Verify that we've actually found a device running the right firmware. num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if (num_interfaces >= 2) { if (dev->device_does_motor_control_with_audio) { dev->motor_control_with_audio_enabled = 1; } } else { FN_SPEW("Opened audio with matching serial but too few interfaces.\n"); dev->usb_audio.dev = NULL; libusb_close(new_dev_handle); continue; } break; } else { FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial); } } } libusb_free_device_list(new_dev_list, 1); // If we found the right device, break out of this loop. if (dev->usb_audio.dev) break; // Sleep for a second to give the device more time to reenumerate. sleep(1); } free(audio_serial); } } else { nr_audio++; } } } libusb_free_device_list (devs, 1); // free the list, unref the devices in it if ((dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA)) && (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))) //&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))) { // Each requested subdevice is open. // Except audio, which may fail if firmware is missing (or because it hates us). return 0; } if (dev->usb_cam.dev != NULL) { libusb_release_interface(dev->usb_cam.dev, 0); libusb_close(dev->usb_cam.dev); } else { FN_ERROR("Failed to open camera subdevice or it is not disabled."); } if (dev->usb_motor.dev != NULL) { libusb_release_interface(dev->usb_motor.dev, 0); libusb_close(dev->usb_motor.dev); } else { FN_ERROR("Failed to open motor subddevice or it is not disabled."); } if (dev->usb_audio.dev != NULL) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); } else { FN_ERROR("Failed to open audio subdevice or it is not disabled."); } return -1; } FN_INTERNAL int fnusb_close_subdevices(freenect_device *dev) { if (dev->usb_cam.dev) { libusb_release_interface(dev->usb_cam.dev, 0); #ifndef _WIN32 libusb_attach_kernel_driver(dev->usb_cam.dev, 0); #endif libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; } if (dev->usb_motor.dev) { libusb_release_interface(dev->usb_motor.dev, 0); libusb_close(dev->usb_motor.dev); dev->usb_motor.dev = NULL; } if (dev->usb_audio.dev) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; } return 0; } static void LIBUSB_CALL iso_callback(struct libusb_transfer *xfer) { int i; fnusb_isoc_stream *strm = (fnusb_isoc_stream*)xfer->user_data; freenect_context *ctx = strm->parent->parent->parent; if (strm->dead) { strm->dead_xfers++; FN_SPEW("EP %02x transfer complete, %d left\n", xfer->endpoint, strm->num_xfers - strm->dead_xfers); return; } switch(xfer->status) { case LIBUSB_TRANSFER_COMPLETED: // Normal operation. { uint8_t *buf = (uint8_t*)xfer->buffer; for (i=0; ipkts; i++) { strm->cb(strm->parent->parent, buf, xfer->iso_packet_desc[i].actual_length); buf += strm->len; } int res; res = libusb_submit_transfer(xfer); if (res != 0) { FN_ERROR("iso_callback(): failed to resubmit transfer after successful completion: %d\n", res); strm->dead_xfers++; if (res == LIBUSB_ERROR_NO_DEVICE) { strm->parent->device_dead = 1; } } break; } case LIBUSB_TRANSFER_NO_DEVICE: { // We lost the device we were talking to. This is a large problem, // and one that we should eventually come up with a way to // properly propagate up to the caller. if(!strm->parent->device_dead) { FN_ERROR("USB device disappeared, cancelling stream %02x :(\n", xfer->endpoint); } strm->dead_xfers++; strm->parent->device_dead = 1; break; } case LIBUSB_TRANSFER_CANCELLED: { if(strm->dead) { FN_SPEW("EP %02x transfer cancelled\n", xfer->endpoint); } else { // This seems to be a libusb bug on OSX - instead of completing // the transfer with LIBUSB_TRANSFER_NO_DEVICE, the transfers // simply come back cancelled by the OS. We can detect this, // though - the stream should be marked dead if we're // intentionally cancelling transfers. if(!strm->parent->device_dead) { FN_ERROR("Got cancelled transfer, but we didn't request it - device disconnected?\n"); } strm->parent->device_dead = 1; } strm->dead_xfers++; break; } default: { // On other errors, resubmit the transfer - in particular, libusb // on OSX tends to hit random errors a lot. If we don't resubmit // the transfers, eventually all of them die and then we don't get // any more data from the Kinect. FN_WARNING("Isochronous transfer error: %d\n", xfer->status); int res; res = libusb_submit_transfer(xfer); if (res != 0) { FN_ERROR("Isochronous transfer resubmission failed after unknown error: %d\n", res); strm->dead_xfers++; if (res == LIBUSB_ERROR_NO_DEVICE) { strm->parent->device_dead = 1; } } break; } } } FN_INTERNAL int fnusb_get_max_iso_packet_size(fnusb_dev *dev, unsigned char endpoint, int default_size) { freenect_context *ctx = dev->parent->parent; int size = libusb_get_max_iso_packet_size(libusb_get_device(dev->dev), endpoint); if (size <= 0) { FN_WARNING("libusb_get_max_iso_packet_size() returned %d; using default %d\n", size, default_size); size = default_size; } return size; } FN_INTERNAL int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, unsigned char endpoint, int xfers, int pkts, int len) { freenect_context *ctx = dev->parent->parent; strm->parent = dev; strm->cb = cb; strm->num_xfers = xfers; strm->pkts = pkts; strm->len = len; strm->buffer = (uint8_t*)malloc(xfers * pkts * len); strm->xfers = (struct libusb_transfer**)malloc(sizeof(struct libusb_transfer*) * xfers); strm->dead = 0; strm->dead_xfers = 0; int i; uint8_t *bufp = strm->buffer; for (i = 0; i < xfers; i++) { FN_SPEW("Creating endpoint %02x transfer #%d\n", endpoint, i); strm->xfers[i] = libusb_alloc_transfer(pkts); if (strm->xfers[i] == NULL) { FN_WARNING("Failed to allocate transfer\n"); strm->dead_xfers++; } else { libusb_fill_iso_transfer(strm->xfers[i], dev->dev, endpoint, bufp, pkts * len, pkts, iso_callback, strm, 0); libusb_set_iso_packet_lengths(strm->xfers[i], len); int ret = libusb_submit_transfer(strm->xfers[i]); if (ret < 0) { FN_WARNING("Failed to submit isochronous transfer %d: %d\n", i, ret); strm->dead_xfers++; } } bufp += pkts*len; } return 0; } FN_INTERNAL int fnusb_stop_iso(fnusb_dev *dev, fnusb_isoc_stream *strm) { freenect_context *ctx = dev->parent->parent; int i; FN_FLOOD("fnusb_stop_iso() called\n"); strm->dead = 1; for (i=0; inum_xfers; i++) libusb_cancel_transfer(strm->xfers[i]); FN_FLOOD("fnusb_stop_iso() cancelled all transfers\n"); while (strm->dead_xfers < strm->num_xfers) { FN_FLOOD("fnusb_stop_iso() dead = %d\tnum = %d\n", strm->dead_xfers, strm->num_xfers); libusb_handle_events(ctx->usb.ctx); } for (i=0; inum_xfers; i++) libusb_free_transfer(strm->xfers[i]); FN_FLOOD("fnusb_stop_iso() freed all transfers\n"); free(strm->buffer); free(strm->xfers); FN_FLOOD("fnusb_stop_iso() freed buffers and stream\n"); FN_FLOOD("fnusb_stop_iso() done\n"); return 0; } FN_INTERNAL int fnusb_control(fnusb_dev *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength) { return libusb_control_transfer(dev->dev, bmRequestType, bRequest, wValue, wIndex, data, wLength, 0); } FN_INTERNAL int fnusb_bulk(fnusb_dev *dev, uint8_t endpoint, uint8_t *data, int len, int *transferred) { *transferred = 0; return libusb_bulk_transfer(dev->dev, endpoint, data, len, transferred, 0); } FN_INTERNAL int fnusb_num_interfaces(fnusb_dev *dev) { int retval = 0; int res; libusb_device* d = libusb_get_device(dev->dev); struct libusb_config_descriptor* config; res = libusb_get_active_config_descriptor(d, &config); if (res < 0) // Something went wrong return res; retval = config->bNumInterfaces; libusb_free_config_descriptor(config); return retval; } libfreenect-0.5.3/src/usb_libusb10.h000066400000000000000000000061711264163024100172370ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" #include // There are a few rules: PKTS_PER_XFER * NUM_XFERS <= 1000, PKTS_PER_XFER % 8 == 0. #if defined(__APPLE__) #define DEPTH_PKTBUF 2048 #define VIDEO_PKTBUF 2048 #define PKTS_PER_XFER 128 #define NUM_XFERS 4 #else #define DEPTH_PKTBUF 1920 #define VIDEO_PKTBUF 1920 #if defined(_WIN32) #define PKTS_PER_XFER 32 #define NUM_XFERS 8 #else #define PKTS_PER_XFER 16 #define NUM_XFERS 16 #endif #endif typedef struct { libusb_context *ctx; int should_free_ctx; } fnusb_ctx; typedef struct { freenect_device *parent; //so we can go up from the libusb userdata libusb_device_handle *dev; int device_dead; // set to 1 when the underlying libusb_device_handle vanishes (ie, Kinect was unplugged) int VID; int PID; } fnusb_dev; typedef struct { fnusb_dev *parent; //so we can go up from the libusb userdata struct libusb_transfer **xfers; uint8_t *buffer; fnusb_iso_cb cb; int num_xfers; int pkts; int len; int dead; int dead_xfers; } fnusb_isoc_stream; int fnusb_num_devices(fnusb_ctx *ctx); int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_device_attributes** attribute_list); int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx); int fnusb_shutdown(fnusb_ctx *ctx); int fnusb_process_events(fnusb_ctx *ctx); int fnusb_process_events_timeout(fnusb_ctx *ctx, struct timeval* timeout); int fnusb_open_subdevices(freenect_device *dev, int index); int fnusb_close_subdevices(freenect_device *dev); int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, unsigned char endpoint, int xfers, int pkts, int len); int fnusb_stop_iso(fnusb_dev *dev, fnusb_isoc_stream *strm); int fnusb_get_max_iso_packet_size(fnusb_dev *dev, unsigned char endpoint, int default_size); int fnusb_control(fnusb_dev *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength); int fnusb_bulk(fnusb_dev *dev, uint8_t endpoint, uint8_t *data, int len, int *transferred); int fnusb_num_interfaces(fnusb_dev *dev); libfreenect-0.5.3/wrappers/000077500000000000000000000000001264163024100156435ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/.gitignore000066400000000000000000000000071264163024100176300ustar00rootroot00000000000000/test/ libfreenect-0.5.3/wrappers/actionscript/000077500000000000000000000000001264163024100203455ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/actionscript/CMakeLists.txt000077500000000000000000000020101264163024100231010ustar00rootroot00000000000000###################################################################################### # ActionScript socket server builder ###################################################################################### find_package(JPEG REQUIRED) include_directories(${JPEG_INCLUDE_DIR}) add_library (as3_jpeg server/as3_jpeg.c) target_link_libraries (as3_jpeg ${JPEG_LIBRARIES}) add_library (freenect_network server/freenect_network.c) if (WIN32) set_source_files_properties(server/as3-server.c PROPERTIES LANGUAGE CXX) set(THREADS_USE_PTHREADS_WIN32 true) find_package(Threads REQUIRED) include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) endif() add_executable(as3-server server/as3-server.c) if(APPLE) set(CMAKE_EXE_LINKER_FLAGS "-framework CoreFoundation -framework IOKit") else(APPLE) find_package(Threads REQUIRED) endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../wrappers/c_sync) target_link_libraries(as3-server freenect_sync_static as3_jpeg freenect_network ${MATH_LIB} ${CMAKE_THREAD_LIBS_INIT}) libfreenect-0.5.3/wrappers/actionscript/org/000077500000000000000000000000001264163024100211345ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/000077500000000000000000000000001264163024100230205ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3KinectCalibrationUI.as000066400000000000000000000431221264163024100276010ustar00rootroot00000000000000package org.as3kinect { import fl.controls.Button; import fl.controls.Label; import fl.controls.Slider; import fl.controls.TextInput; import fl.events.SliderEvent; import flash.display.Bitmap; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.geom.Point; import flash.text.TextField; import org.as3kinect.events.as3kinectCalibrationEvent; import org.as3kinect.objects.as3kinectCalibrationParams; public class as3KinectCalibrationUI extends Sprite { private var _calibrationAreas : Array; private var _originalCoordinates : Object; private var _as3w : as3kinectWrapper; private var _bmpDepth : Bitmap; private var _sliceRect : Sprite; private var _minDistanceValueLabel : TextInput; private var _maxDistanceValueLabel : TextInput; private var _minDistanceSlider : Slider; private var _maxDistanceSlider : Slider; private var _sliceHeightValueLabel : TextInput; private var _sliceHeightSlider : Slider; private var _sliceYPosValueLabel : TextInput; private var _sliceYPosSlider : Slider; private var _calculateBtn : Button; private var _params : as3kinectCalibrationParams; private var _active : Boolean; public function as3KinectCalibrationUI(as3w : as3kinectWrapper) { _as3w = as3w; _calibrationAreas = []; _as3w.depth.compression = 100; _params = new as3kinectCalibrationParams(); _originalCoordinates = [new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0)]; } public function activate() : void { if (_active) return; _active = true; as3kinectUtils.calibrationParams = null; this.addEventListener(Event.ENTER_FRAME, update); // Add depth BitmapData to depth_cam MovieClip _bmpDepth = new Bitmap(_as3w.depth.bitmap); _bmpDepth.x = 300; _bmpDepth.y = 120; addChild(_bmpDepth); initUI(); } public function deactivate() : void { for (var i : int = 0; i < _calibrationAreas.length; i++) { _calibrationAreas[i].btn.removeEventListener(MouseEvent.CLICK, calibrateBtnClickListener); } _minDistanceSlider.removeEventListener(SliderEvent.CHANGE, minDinstanceSliderChangeListener); _minDistanceSlider.removeEventListener(SliderEvent.THUMB_DRAG, minDinstanceSliderChangeListener); _minDistanceValueLabel.removeEventListener(KeyboardEvent.KEY_DOWN, minDistanceTfListener); _maxDistanceSlider.removeEventListener(SliderEvent.CHANGE, maxDinstanceSliderChangeListener); _maxDistanceSlider.removeEventListener(SliderEvent.THUMB_DRAG, maxDinstanceSliderChangeListener); _maxDistanceValueLabel.removeEventListener(KeyboardEvent.KEY_DOWN, maxDistanceTfListener); _sliceHeightSlider.removeEventListener(SliderEvent.CHANGE, sliceHeightSliderChangeListener); _sliceHeightSlider.removeEventListener(SliderEvent.THUMB_DRAG, sliceHeightSliderChangeListener); _sliceHeightValueLabel.removeEventListener(KeyboardEvent.KEY_DOWN, sliceHeightTfListener); _sliceYPosSlider.removeEventListener(SliderEvent.CHANGE, sliceYPosSliderChangeListener); _sliceYPosSlider.removeEventListener(SliderEvent.THUMB_DRAG, sliceYPosSliderChangeListener); _calculateBtn.removeEventListener(MouseEvent.CLICK, calculateBtnListener); _sliceYPosValueLabel.removeEventListener(KeyboardEvent.KEY_DOWN, sliceYPosTfListener); do { removeChildAt(0); } while (numChildren > 0); _active = false; _calibrationAreas = []; } private function initUI() : void { var rect : Sprite; var tf : TextField; var calibrateCornerBtn : Button; for (var i : int = 0; i < 4; i++) { rect = new Sprite(); rect.visible = false; tf = new TextField(); tf.visible = false; calibrateCornerBtn = new Button(); calibrateCornerBtn.visible = false; calibrateCornerBtn.label = "calibrate corner "; calibrateCornerBtn.name = i.toString(); calibrateCornerBtn.addEventListener(MouseEvent.CLICK, calibrateBtnClickListener); // calibration Rectangle with(rect.graphics) { beginFill(0x00FF00); if (i == 0) drawRect(0, 0, 50, 50); if (i == 1) drawRect(stage.stageWidth - 50, 0, 50, 50); if (i == 2) drawRect(0, stage.stageHeight - 50, 50, 50); if (i == 3) drawRect(stage.stageWidth - 50, stage.stageHeight - 50, 50, 50); endFill(); } addChild(rect); // Textfield and Button switch (i) { case 0: tf.x = rect.width + 10; tf.y = 20; calibrateCornerBtn.move(rect.width + 10, 0); break; case 1: tf.x = stage.stageWidth - 100 - rect.width - 10; tf.y = 20; calibrateCornerBtn.move(stage.stageWidth - 100 - rect.width - 10, 0); break; case 2: tf.x = rect.width + 10; tf.y = stage.stageHeight - 30; calibrateCornerBtn.move(rect.width + 10, stage.stageHeight - 50); break; case 3: tf.x = stage.stageWidth - 100 - rect.width - 10; tf.y = stage.stageHeight - 30; calibrateCornerBtn.move(stage.stageWidth - 100 - rect.width - 10, stage.stageHeight - 50); break; } tf.text = _originalCoordinates[i]; addChild(tf); addChild(calibrateCornerBtn); _calibrationAreas.push({rect:rect, tf:tf, btn:calibrateCornerBtn}); } _sliceRect = new Sprite(); with(_sliceRect.graphics) { lineStyle(1, 0xFF00FF); drawRect(_bmpDepth.x, _bmpDepth.y, _bmpDepth.width, _params.sliceRectHeight); } _sliceRect.y = _params.sliceRectY; addChild(_sliceRect); _minDistanceSlider = createSlider(_bmpDepth.x + _bmpDepth.width + 40, _bmpDepth.y, 200, 10, 0, 1000, 90); _minDistanceSlider.addEventListener(SliderEvent.CHANGE, minDinstanceSliderChangeListener); _minDistanceSlider.addEventListener(SliderEvent.THUMB_DRAG, minDinstanceSliderChangeListener); _minDistanceSlider.value = _as3w.depth.minDistance; var minDistanceLabel : Label = new Label(); minDistanceLabel.x = _minDistanceSlider.x; minDistanceLabel.y = _minDistanceSlider.y; minDistanceLabel.text = "min. distance"; addChild(minDistanceLabel); _minDistanceValueLabel = createInputTf(_minDistanceSlider.x - 15, _minDistanceSlider.y + _minDistanceSlider.width + 2, 30, 15, "0-9"); _minDistanceValueLabel.text = _minDistanceSlider.value.toString(); _minDistanceValueLabel.addEventListener(KeyboardEvent.KEY_DOWN, minDistanceTfListener); addChild(_minDistanceValueLabel); _maxDistanceSlider = createSlider(_bmpDepth.x + _bmpDepth.width + 40, _bmpDepth.y + 250, 200, 10, 0, 1000, 90); _maxDistanceSlider.addEventListener(SliderEvent.CHANGE, maxDinstanceSliderChangeListener); _maxDistanceSlider.addEventListener(SliderEvent.THUMB_DRAG, maxDinstanceSliderChangeListener); _maxDistanceSlider.value = _as3w.depth.maxDistance; var maxDistanceLabel : Label = new Label(); maxDistanceLabel.x = _maxDistanceSlider.x; maxDistanceLabel.y = _maxDistanceSlider.y; maxDistanceLabel.text = "max. distance"; addChild(maxDistanceLabel); _maxDistanceValueLabel = createInputTf(_maxDistanceSlider.x - 15, _maxDistanceSlider.y + _maxDistanceSlider.width + 2, 30, 15, "0-9"); _maxDistanceValueLabel.text = _maxDistanceSlider.value.toString(); _maxDistanceValueLabel.addEventListener(KeyboardEvent.KEY_DOWN, maxDistanceTfListener); addChild(_maxDistanceValueLabel); _sliceHeightSlider = createSlider(_bmpDepth.x + 100, _bmpDepth.y - 70, 300, 10, 0, 480); _sliceHeightSlider.addEventListener(SliderEvent.CHANGE, sliceHeightSliderChangeListener); _sliceHeightSlider.addEventListener(SliderEvent.THUMB_DRAG, sliceHeightSliderChangeListener); _sliceHeightSlider.value = _params.sliceRectHeight; var sliceHeightLabel : Label = new Label(); sliceHeightLabel.x = _sliceHeightSlider.x; sliceHeightLabel.y = _sliceHeightSlider.y - 20; sliceHeightLabel.text = "slice height"; addChild(sliceHeightLabel); _sliceHeightValueLabel = createInputTf(_sliceHeightSlider.x + _sliceHeightSlider.width + 8, _sliceHeightSlider.y - 6, 30, 15, "0-9"); _sliceHeightValueLabel.text = _sliceHeightSlider.value.toString(); _sliceHeightValueLabel.addEventListener(KeyboardEvent.KEY_DOWN, sliceHeightTfListener); _sliceYPosSlider = createSlider(_bmpDepth.x + 100, _bmpDepth.y - 20, 300, 0, 0, 480); _sliceYPosSlider.addEventListener(SliderEvent.CHANGE, sliceYPosSliderChangeListener); _sliceYPosSlider.addEventListener(SliderEvent.THUMB_DRAG, sliceYPosSliderChangeListener); _sliceYPosSlider.value = _params.sliceRectY; var sliceYPosLabel : Label = new Label(); sliceYPosLabel.x = _sliceYPosSlider.x; sliceYPosLabel.y = _sliceYPosSlider.y - 20; sliceYPosLabel.text = "slice yPos"; addChild(sliceYPosLabel); _sliceYPosValueLabel = createInputTf(_sliceYPosSlider.x + _sliceYPosSlider.width + 8, _sliceYPosSlider.y - 6, 30, 15, "0-9"); _sliceYPosValueLabel.text = _sliceYPosSlider.value.toString(); _sliceYPosValueLabel.addEventListener(KeyboardEvent.KEY_DOWN, sliceYPosTfListener); _calculateBtn = new Button(); _calculateBtn.label = "next step "; _calculateBtn.x = stage.stageWidth / 2; _calculateBtn.y = stage.stageHeight - 50; _calculateBtn.addEventListener(MouseEvent.CLICK, calculateBtnListener); addChild(_calculateBtn); // first depth init _as3w.depth.minDistance = _minDistanceSlider.value; _as3w.depth.maxDistance = _maxDistanceSlider.value; } private function minDinstanceSliderChangeListener(event : SliderEvent) : void { _as3w.depth.minDistance = event.value; _minDistanceValueLabel.text = event.value.toString(); } private function maxDinstanceSliderChangeListener(event : SliderEvent) : void { _as3w.depth.maxDistance = event.value; _maxDistanceValueLabel.text = event.value.toString(); } private function sliceHeightSliderChangeListener(event : SliderEvent) : void { with(_sliceRect.graphics) { clear(); lineStyle(1, 0xFF00FF); drawRect(_bmpDepth.x, _bmpDepth.y, _bmpDepth.width, event.value); } _sliceHeightValueLabel.text = event.value.toString(); } private function sliceYPosSliderChangeListener(event : SliderEvent) : void { _sliceRect.y = event.value; _sliceYPosValueLabel.text = event.value.toString(); } private function minDistanceTfListener(event : KeyboardEvent) : void { if (event.keyCode == 13) { _minDistanceSlider.value = Number(_minDistanceValueLabel.text); _as3w.depth.minDistance = _minDistanceSlider.value; } } private function maxDistanceTfListener(event : KeyboardEvent) : void { if (event.keyCode == 13) { _maxDistanceSlider.value = Number(_maxDistanceValueLabel.text); _as3w.depth.maxDistance = _maxDistanceSlider.value; } } private function sliceHeightTfListener(event : KeyboardEvent) : void { if (event.keyCode == 13) { with(_sliceRect.graphics) { clear(); lineStyle(1, 0xFF00FF); drawRect(_bmpDepth.x, _bmpDepth.y, _bmpDepth.width, Number(_sliceHeightValueLabel.text)); } _sliceHeightSlider.value = Number(_sliceHeightValueLabel.text); } } private function sliceYPosTfListener(event : KeyboardEvent) : void { if (event.keyCode == 13) { _sliceRect.y = Number(_sliceYPosValueLabel.text); _sliceYPosSlider.value = Number(_sliceYPosValueLabel.text); } } private function calculateBtnListener(event : MouseEvent) : void { if (event.target.label == "next step ") { event.target.label = "calculate "; for (var i : int = 0; i < numChildren; i++) getChildAt(i).visible = false; for (var j : int = 0; j < _calibrationAreas.length; j++) { _calibrationAreas[j].rect.visible = true; _calibrationAreas[j].tf.visible = true; _calibrationAreas[j].btn.visible = true; } event.target.visible = true; setStepOne(); dispatchEvent(new as3kinectCalibrationEvent(as3kinectCalibrationEvent.CALIBRATION_STEP_ONE)); } else { setStepTwo(); dispatchEvent(new as3kinectCalibrationEvent(as3kinectCalibrationEvent.CALIBRATION_COMPLETE)); } } private function setStepOne() : void { as3kinectUtils.calibrationParams = _params; _params.sliceRectY = _sliceRect.y; _params.sliceRectHeight = _sliceHeightSlider.value; } private function setStepTwo() : void { _params.screenWidth = stage.stageWidth; _params.screenHeight = stage.stageHeight; _params.yOffset = (_originalCoordinates[2].y + _originalCoordinates[3].y) / 2 ; var yFactor : Number = ( (_originalCoordinates[0].y + _originalCoordinates[1].y) / 2 - _params.yOffset) / 100; _params.yScreenFactor = int(_params.screenHeight / yFactor) / 100; _params.xOffsetTop = _originalCoordinates[0].x; var xOffsetBottom : Number = _originalCoordinates[2].x; _params.xOffsetDifference = xOffsetBottom - _params.xOffsetTop; var xFactorTop : Number = int((100 / (_originalCoordinates[1].x - _originalCoordinates[0].x)) * 100) / 100 ; var xFactorBottom : Number = int((100 / (_originalCoordinates[3].x - _originalCoordinates[2].x)) * 100) / 100; _params.xScreenFactorTop = xFactorTop * _params.screenWidth / 100; var xScreenFactorBottom : Number = xFactorBottom * _params.screenWidth / 100; _params.xScreenFactorDifference = xScreenFactorBottom - _params.xScreenFactorTop; _params.calibrationComplete = true; } private function calibrateBtnClickListener(event : MouseEvent) : void { if (as3kinectUtils.registeredBlobs.length > 0) { _calibrationAreas[int(event.target.name)].tf.text = "xPos:" + as3kinectUtils.registeredBlobs[0].x; _calibrationAreas[int(event.target.name)].tf.text += "\nyPos:" + as3kinectUtils.registeredBlobs[0].y * -1; _originalCoordinates[int(event.target.name)].x = as3kinectUtils.registeredBlobs[0].x; _originalCoordinates[int(event.target.name)].y = as3kinectUtils.registeredBlobs[0].y * -1; } } private function update(event : Event) : void { _as3w.depth.getBuffer(); } private function createInputTf(x : Number, y : Number, w : Number, h : Number, restr : String) : TextInput { var inputTf : TextInput = new TextInput(); inputTf.x = x; inputTf.y = y; inputTf.width = w; inputTf.height = h; inputTf.restrict = restr; addChild(inputTf); return inputTf; } private function createSlider(x : Number, y : Number, w : Number, h : Number, min : Number, max : Number, rot : Number = 0) : Slider { var slider : Slider = new Slider(); slider.x = x; slider.y = y; slider.setSize(w, h); slider.minimum = min; slider.maximum = max; slider.rotation = rot; addChild(slider); return slider; } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinect.as000077500000000000000000000056261264163024100252450ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import flash.utils.ByteArray; public class as3kinect { public static const SUCCESS:int = 0; public static const ERROR:int = -1; public static const SERVER_IP:String = "localhost"; public static const SOCKET_PORT:int = 6001; public static const CAMERA_ID:int = 0; public static const MOTOR_ID:int = 1; public static const MIC_ID:int = 2; public static const GET_DEPTH:int = 0; public static const GET_RAW_DEPTH:int = 1; public static const GET_VIDEO:int = 2; public static const MIRROR_DEPTH:int = 3; public static const MIRROR_VIDEO:int = 4; public static const MIN_DEPTH:int = 5; public static const MAX_DEPTH:int = 6; public static const DEPTH_COMPRESSION:int = 7; public static const VIDEO_COMPRESSION:int = 8; public static const MOVE_MOTOR:int = 0; public static const LED_COLOR:int = 1; public static const ACCEL_DATA:int = 2; public static const IMG_WIDTH:int = 640; public static const IMG_HEIGHT:int = 480; public static const RAW_IMG_SIZE:int = IMG_WIDTH * IMG_HEIGHT * 4; public static const DATA_IN_SIZE:int = 3 * 2 + 3 * 8; public static const COMMAND_SIZE:int = 6; public static const MAX_BLOBS:int = 15; public static const BLOB_MASK:uint = 0xFFFFFFFF; public static const BLOB_COLOR:uint = 0xFFFFFFFF; public static const BLOB_FILL_COLOR:uint = 0xFF0000FF; public static const BLOB_PROCESSED_COLOR:uint = 0x00FF00FF; public static const BLOB_MIN_WIDTH:uint = 15; public static const BLOB_MAX_WIDTH:uint = 30; public static const BLOB_MIN_HEIGHT:uint = 15; public static const BLOB_MAX_HEIGHT:uint = 80; public static const HORIZONTAL_BLOBS_SEARCH_STEP_WIDTH : int = 3; public static const HORIZONTAL_BLOBS_SEARCH_SENSIVITY : int = 15; public static const HORIZONTAL_BLOBS_HOLD_TOLERANCE : int=100; } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectDepth.as000077500000000000000000000112231264163024100262200ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import org.as3kinect.as3kinect; import org.as3kinect.as3kinectSocket; import flash.utils.ByteArray; import flash.display.BitmapData; public class as3kinectDepth { private var _socket:as3kinectSocket; private var _data:ByteArray; private var _depth_busy:Boolean; private var _is_mirrored:Boolean; private var _min_distance:int; private var _max_distance:int; private var _compression:int; public var bitmap:BitmapData; public function as3kinectDepth(){ _socket = as3kinectSocket.instance; _data = new ByteArray; _depth_busy = false; _is_mirrored = false; _min_distance = 600; _max_distance = 800; _compression = 20; bitmap = new BitmapData(as3kinect.IMG_WIDTH, as3kinect.IMG_HEIGHT, false, 0xFF000000); } /* * Tell server to send the latest depth frame * Note: We should lock the command while we are waiting for the data to avoid lag */ public function getBuffer():void { if(!_depth_busy){ _depth_busy = true; _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.GET_DEPTH); _data.writeInt(0); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Data was not complete'); } } } /* * Tell server to send the latest depth raw frame * Note: We should lock the command while we are waiting for the data to avoid lag */ public function getRawBuffer():void { if(!_depth_busy){ _depth_busy = true; _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.GET_RAW_DEPTH); _data.writeInt(0); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Data was not complete'); } } } public function set busy(flag:Boolean):void { _depth_busy = flag; } public function get busy():Boolean { return _depth_busy; } public function set mirrored(flag:Boolean):void { _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.MIRROR_DEPTH); _data.writeInt(int(flag)); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Depth: Cannot change mirror state'); } else { _is_mirrored = flag; } } public function get mirrored():Boolean { return _is_mirrored; } public function set minDistance(distance:int):void { _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.MIN_DEPTH); _data.writeInt(int(distance)); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Depth: Cannot change mirror state'); } else { _min_distance = distance; } } public function get minDistance():int { return _min_distance; } public function set maxDistance(distance:int):void { _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.MAX_DEPTH); _data.writeInt(int(distance)); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Depth: Cannot change mirror state'); } else { _max_distance = distance; } } public function get maxDistance():int { return _max_distance; } public function set compression(quality:int):void { _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.DEPTH_COMPRESSION); _data.writeInt(int(quality)); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Depth: Cannot change depth compression'); } else { _compression = quality; } } public function get compression():int { return _compression; } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectMotor.as000077500000000000000000000070701264163024100262610ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import org.as3kinect.as3kinect; import org.as3kinect.as3kinectSocket; import org.as3kinect.objects.motorData; import flash.utils.ByteArray; public class as3kinectMotor { private var _socket:as3kinectSocket; private var _data:ByteArray; private var _motor_busy:Boolean; private var _motor_data:motorData; private var _motor_position:Number; public function as3kinectMotor(){ _socket = as3kinectSocket.instance; _data = new ByteArray; _motor_busy = false; _motor_data = new motorData; _motor_position = 0; } /* * Tell server to send the latest depth frame * Note: We should lock the command while we are waiting for the data to avoid lag */ public function getData():void { if(!_motor_busy){ _motor_busy = true; _data.clear(); _data.writeByte(as3kinect.MOTOR_ID); _data.writeByte(as3kinect.ACCEL_DATA); _data.writeInt(0); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Data was not complete'); } } } /* * Set motor data from ByteArray */ public function updateDataFromBytes(bytes:ByteArray):void{ _motor_data.ax = bytes.readShort(); _motor_data.ay = bytes.readShort(); _motor_data.az = bytes.readShort(); _motor_data.dx = bytes.readDouble(); _motor_data.dy = bytes.readDouble(); _motor_data.dz = bytes.readDouble(); } public function get data():motorData { return _motor_data; } public function set data(data:motorData):void { _motor_data = data; } public function set busy(flag:Boolean):void { _motor_busy = flag; } public function get busy():Boolean { return _motor_busy; } public function set position(position:Number):void { _data.clear(); _data.writeByte(as3kinect.MOTOR_ID); _data.writeByte(as3kinect.MOVE_MOTOR); _data.writeInt(position); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Data was not complete'); } else { _motor_position = position; } } public function get position():Number { return _motor_position; } // 0 = Turn Off // 1 = Green // 2 = Red // 3 = Orange // 4 = Blink Green-Off // 6 = Blink Red-Orange public function set ledColor(color:Number):void { _data.clear(); _data.writeByte(as3kinect.MOTOR_ID); _data.writeByte(as3kinect.LED_COLOR); _data.writeInt(color); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Data was not complete'); } } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectSocket.as000077500000000000000000000105751264163024100264150ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import org.as3kinect.as3kinect; import org.as3kinect.events.as3kinectSocketEvent; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.ProgressEvent; import flash.events.IOErrorEvent; import flash.net.Socket; import flash.utils.ByteArray; import flash.utils.Endian; /** * as3kinectSocket class recieves Kinect data from the as3kinect driver. */ public class as3kinectSocket extends EventDispatcher { private static var _instance:as3kinectSocket; private static var _singleton_lock:Boolean = false; private var _first_byte:Number; private var _second_byte:Number; private var _packet_size:Number; private var _socket:Socket; private var _buffer:ByteArray; private var _data_obj:Object; private var _port:Number; public function as3kinectSocket() { if ( !_singleton_lock ) throw new Error( 'Use as3kinectSocket.instance' ); _socket = new Socket(); _buffer = new ByteArray(); _data_obj = new Object(); _socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData); _socket.addEventListener(IOErrorEvent.IO_ERROR, onSocketError); _socket.addEventListener(Event.CONNECT, onSocketConnect); } public function connect(host:String = 'localhost', port:uint = 6001):void { _port = port; _packet_size = 0; if (!this.connected) _socket.connect(host, port); else dispatchEvent(new as3kinectSocketEvent(as3kinectSocketEvent.ONCONNECT, null)); } public function get connected():Boolean { return _socket.connected; } public function close():void { _socket.close(); } public function sendCommand(data:ByteArray):int{ if(data.length == as3kinect.COMMAND_SIZE){ _socket.writeBytes(data, 0, as3kinect.COMMAND_SIZE); _socket.flush(); return as3kinect.SUCCESS; } else { throw new Error( 'Incorrect data size (' + data.length + '). Expected: ' + as3kinect.COMMAND_SIZE); return as3kinect.ERROR; } } private function onSocketData(event:ProgressEvent):void { if(_socket.bytesAvailable > 0) { if(_packet_size == 0) { _socket.endian = Endian.LITTLE_ENDIAN; _first_byte = _socket.readByte(); _second_byte = _socket.readByte(); _packet_size = _socket.readInt(); } if(_socket.bytesAvailable >= _packet_size && _packet_size != 0){ _socket.readBytes(_buffer, 0, _packet_size); _buffer.endian = Endian.LITTLE_ENDIAN; _buffer.position = 0; _data_obj.first = _first_byte; _data_obj.second = _second_byte; _data_obj.buffer = _buffer; _packet_size = 0; dispatchEvent(new as3kinectSocketEvent(as3kinectSocketEvent.ONDATA, _data_obj)); } } } private function onSocketError(event:IOErrorEvent):void{ dispatchEvent(new as3kinectSocketEvent(as3kinectSocketEvent.ONERROR, null)); } private function onSocketConnect(event:Event):void{ dispatchEvent(new as3kinectSocketEvent(as3kinectSocketEvent.ONCONNECT, null)); } public function set instance(instance:as3kinectSocket):void { throw new Error('as3kinectSocket.instance is read-only'); } public static function get instance():as3kinectSocket { if ( _instance == null ) { _singleton_lock = true; _instance = new as3kinectSocket(); _singleton_lock = false; } return _instance; } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectUI.as000066400000000000000000000202161264163024100254700ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import com.bit101.components.*; import com.bit101.charts.*; import flash.display.DisplayObjectContainer; import flash.events.MouseEvent; import org.as3kinect.as3kinectWrapper; import org.as3kinect.objects.motorData; import flash.events.Event; public class as3kinectUI { var _as3w :as3kinectWrapper; var info :Text; public var depth_enabled :Boolean = true; public var video_enabled :Boolean = true; public var motor_enabled :Boolean = true; public var blobs_on :Boolean = false; public var wb_filter_on :Boolean = false; public var threshold_value :int = 50; public function as3kinectUI(wrapper:as3kinectWrapper):void{ _as3w = wrapper; } public function showLedPanel(where:DisplayObjectContainer, _x:int, _y:int, _closed:Boolean = false, _draggable:Boolean = true, _color:int = 0xFFFFFF):void{ var ledControl:Window = new Window(where, _x, _y, "Led Control"); ledControl.minimized = _closed; ledControl.draggable = _draggable; ledControl.color = _color; ledControl.hasMinimizeButton = true; ledControl.width = 110; ledControl.height = 175; new PushButton(ledControl.content, 5, 5, "Off", function(e:MouseEvent){ _as3w.motor.ledColor = 0; }); new PushButton(ledControl.content, 5, 30, "Green", function(e:MouseEvent){ _as3w.motor.ledColor = 1; }); new PushButton(ledControl.content, 5, 55, "Red", function(e:MouseEvent){ _as3w.motor.ledColor = 2; }); new PushButton(ledControl.content, 5, 80, "Orange", function(e:MouseEvent){ _as3w.motor.ledColor = 3; }); new PushButton(ledControl.content, 5, 105, "Blink (Green)", function(e:MouseEvent){ _as3w.motor.ledColor = 4; }); new PushButton(ledControl.content, 5, 130, "Blink (Red)",function(e:MouseEvent){ _as3w.motor.ledColor = 6; }); } public function showDepthPanel(where:DisplayObjectContainer, _x:int, _y:int, _closed:Boolean = false, _draggable:Boolean = true, _color:int = 0xFFFFFF):void { var depthControl:Window = new Window(where, _x, _y, "Depth Control"); depthControl.minimized = _closed; depthControl.draggable = _draggable; depthControl.color = _color; depthControl.hasMinimizeButton = true; depthControl.width = 185; depthControl.height = 150; //Enable depth transmission var d_enabled:CheckBox = new CheckBox(depthControl.content, 5, 5, "Enabled", function(e:MouseEvent){ depth_enabled = e.target.selected; }); d_enabled.selected = depth_enabled; //Switch depth mirroring new CheckBox(depthControl.content, 5, 20, "Mirror image", function(e:MouseEvent){ _as3w.depth.mirrored = e.target.selected; }); //Switch blob generation var blob_process:CheckBox = new CheckBox(depthControl.content, 5, 35, "Process blobs", function(e:MouseEvent){ blobs_on = e.target.selected; //Blob generation requires white/black filtering on if(blobs_on) bw_filter.selected = wb_filter_on = true; }); //Switch black/white filter var bw_filter:CheckBox = new CheckBox(depthControl.content, 5, 50, "Enable BW Filter",function(e:MouseEvent){ wb_filter_on = e.target.selected; //Blob generation requires white/black filtering on if(!wb_filter_on) { blob_process.selected = blobs_on = false; } }); new Label(depthControl.content, 5, 70, "Range"); //Depth range slider var d_range:HRangeSlider = new HRangeSlider(depthControl.content, 40, 80, function(e:Event){ _as3w.depth.maxDistance = e.target.highValue; _as3w.depth.minDistance = e.target.lowValue; }); d_range.maximum = 2000; d_range.width = 125; d_range.highValue = _as3w.depth.maxDistance; d_range.lowValue = _as3w.depth.minDistance; //JPEG quality slider var d_quality:HUISlider = new HUISlider(depthControl.content, 5, 95, "Quality", function(e:Event){ _as3w.depth.compression = int(e.target.value); }); d_quality.value = _as3w.depth.compression; //Threshold level slider var th_value:HUISlider = new HUISlider(depthControl.content, 5, 110, "Threshold", function(e:Event){ threshold_value = e.target.value; }); th_value.maximum = 255; th_value.value = threshold_value; } public function showVideoPanel(where:DisplayObjectContainer, _x:int, _y:int, _closed:Boolean = false, _draggable:Boolean = true, _color:int = 0xFFFFFF):void { var videoControl:Window = new Window(where, _x, _y, "Video Control"); videoControl.minimized = _closed; videoControl.draggable = _draggable; videoControl.color = _color; videoControl.hasMinimizeButton = true; videoControl.width = 185; videoControl.height = 75; //Enable video transmission var v_enabled:CheckBox = new CheckBox(videoControl.content, 5, 5, "Enabled", function(e:MouseEvent){ video_enabled = e.target.selected; }); v_enabled.selected = video_enabled; //Switch video mirroring new CheckBox(videoControl.content, 5, 20, "Mirror image", function(e:MouseEvent){ _as3w.video.mirrored = e.target.selected; }); //JPEG quality slider var v_quality:HUISlider = new HUISlider(videoControl.content, 5, 35, "Quality", function(e:Event){ _as3w.video.compression = int(e.target.value); }); v_quality.value = _as3w.video.compression; } public function showMotorPanel(where:DisplayObjectContainer, _x:int, _y:int, _closed:Boolean = false, _draggable:Boolean = true, _color:int = 0xFFFFFF):void { var motorControl:Window = new Window(where, _x, _y, "Motor Control"); motorControl.minimized = _closed; motorControl.draggable = _draggable; motorControl.color = _color; motorControl.hasMinimizeButton = true; motorControl.width = 185; motorControl.height = 65; //Enable motor transmission var m_enabled:CheckBox = new CheckBox(motorControl.content, 5, 5, "Enabled", function(e:MouseEvent){ motor_enabled = e.target.selected; }); m_enabled.selected = motor_enabled; var m_position:HUISlider = new HUISlider(motorControl.content, 5, 20, "Angle", function(e:Event){ _as3w.motor.position = int(e.target.value); }); m_position.tick = 1; m_position.minimum = -31; m_position.maximum = 31; m_position.value = _as3w.motor.position; } public function showAccelerometersDisplay(where:DisplayObjectContainer, _x:int, _y:int, _closed:Boolean = false, _draggable:Boolean = true, _color:int = 0xFFFFFF):void { var motorData:Window = new Window(where, _x, _y, "Motor Data"); motorData.minimized = _closed; motorData.draggable = _draggable; motorData.color = _color; motorData.hasMinimizeButton = true; motorData.width = 185; motorData.height = 150; info = new Text(motorData.content); info.text = "raw acceleration:\n\tax: 0\n\tay: 0\n\taz: 0\n\n"; info.text += "mks acceleration:\n\tdx: 0\n\tdy: 0\n\tdz: 0"; info.height = 150; } public function updateAccelerometerDisplay(object:motorData):void { info.text = "raw acceleration:\n\tax: " + object.ax + "\n\tay: " + object.ay + "\n\taz: " + object.az + "\n\n"; info.text += "mks acceleration:\n\tdx: " + object.dx + "\n\tdy: " + object.dy + "\n\tdz: " + object.dz + "\n"; } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectUtils.as000077500000000000000000000316731264163024100262670ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.display.Loader; import flash.display.Stage; import flash.events.Event; import flash.events.TouchEvent; import flash.filters.ColorMatrixFilter; import flash.geom.Point; import flash.geom.Rectangle; import flash.utils.ByteArray; import org.as3kinect.objects.PointWithID; import org.as3kinect.objects.as3kinectCalibrationParams; public class as3kinectUtils { private static var _registeredBlobs : Array = []; private static var _registerId : Number = 1; private static var _cParams : as3kinectCalibrationParams; /* * Draw ARGB from ByteArray to BitmapData object */ public static function byteArrayToBitmapData(bytes:ByteArray, _canvas:BitmapData):void{ _canvas.lock(); _canvas.setPixels(new Rectangle(0,0, as3kinect.IMG_WIDTH, as3kinect.IMG_HEIGHT), bytes); _canvas.unlock(); } /* * Draw JPEG from ByteArray to BitmapData object */ public static function JPEGToBitmapData(bytes:ByteArray, _canvas:BitmapData):void{ var ldr:Loader = new Loader(); ldr.loadBytes(bytes); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void{ _canvas.draw(ldr.content); }); } /* * Process blobs from BitmapData, if _w and _h set they will be returned in that resoluton */ public static function getBlobs(r:BitmapData, _w:Number = 0, _h:Number = 0):Array { //if _w and _h not specified use as3kinect constants if(_w == 0) _w = as3kinect.IMG_WIDTH; if(_h == 0) _h = as3kinect.IMG_HEIGHT; var i:int; var blobs:Array = new Array(); //Looking fot the blobs while (i < as3kinect.MAX_BLOBS) { //Look for BLOB_COLOR in the BitmapData and genrate a rectanglo enclosing the Blobs of that color var mainRect:Rectangle = r.getColorBoundsRect(as3kinect.BLOB_MASK, as3kinect.BLOB_COLOR); //No blobs found (Exit) if (mainRect.isEmpty()) break; var xx:int = mainRect.x; //Looking in mainRect for a pixel with BLOB_COLOR for (var yy:uint = mainRect.y; yy < mainRect.y + mainRect.height; yy++) { if (r.getPixel32(xx, yy) == as3kinect.BLOB_COLOR) { //Use floodFill to paint that blob to BLOB_FILL_COLOR (works like paint fill tool) r.floodFill(xx, yy, as3kinect.BLOB_FILL_COLOR); //Now our blob is not BLOB_COLOR we get the rect of our recently painted blob (this is our i blob) var blobRect:Rectangle = r.getColorBoundsRect(as3kinect.BLOB_MASK, as3kinect.BLOB_FILL_COLOR); //Looking if our blob fits our desired min/max width and height if (blobRect.width > as3kinect.BLOB_MIN_WIDTH && blobRect.width < as3kinect.BLOB_MAX_WIDTH && blobRect.height > as3kinect.BLOB_MIN_HEIGHT && blobRect.height < as3kinect.BLOB_MAX_HEIGHT) { //Create the blob object var blob:Object = {}; //Add a rect to the object blob.rect = blobRect; //Convert blob positions to float and then multiply per requested width and height blob.rect.x = ((blob.rect.x / as3kinect.IMG_WIDTH) * _w); blob.rect.y = ((blob.rect.y / as3kinect.IMG_HEIGHT) * _h); blob.rect.width = (blob.rect.width / as3kinect.IMG_WIDTH) * _w; blob.rect.height = (blob.rect.height / as3kinect.IMG_HEIGHT) * _h; //The point is the center of the rect var _x:int = blob.rect.x + (blob.rect.width / 2); var _y:int = blob.rect.y + (blob.rect.height / 2); //Add a point to the object blob.point = new Point(_x, _y); blobs.push(blob); } //Finally we paint our blob to a BLOB_PROCESSED_COLOR so we can discard it in the next pass r.floodFill(xx, yy, as3kinect.BLOB_PROCESSED_COLOR); } } i++; } return blobs; } /* * Convert a BitmapData into black and white BitmapData with a ColorMatrixFilter */ public static function setBlackWhiteFilter(obj:BitmapData, threshold:int = 128):void { var rLum:Number = 0.2225; var gLum:Number = 0.7169; var bLum:Number = 0.0606; var matrix:Array = [rLum * 256, gLum * 256, bLum * 256, 0, -256 * threshold, rLum * 256, gLum * 256, bLum * 256, 0, -256 * threshold, rLum * 256, gLum * 256, bLum * 256, 0, -256 * threshold, 0, 0, 0, 1, 0 ]; var filter:ColorMatrixFilter = new ColorMatrixFilter(matrix); obj.applyFilter(obj, new Rectangle(0,0,obj.width,obj.height), new Point(0,0), filter); } /* * Fire a touch event in the desired point * Id is used so we can detect the TouchOut of that specific point * _lastTouched Array is used to store whether this point has already been fired or not * _stage is needed to have access to getObjectsUnderPoint */ public static function fireTouchEvent(id:int, point:Point,_lastTouched:Array, _stage:Stage):void { if(_lastTouched[id] == undefined) _lastTouched[id] = new Array; var targets:Array = _stage.getObjectsUnderPoint(point); var i:int; var max:int; var found:Boolean; var local:Point; //We look in the lastTouched arrar for this point id for (var key : * in _lastTouched[id]) { //If TOUCH_OVER was already fired we look for it in the new targets object if (_lastTouched[id][key].bool != false) { found = false; for (i = 0,max = targets.length; i < max; i++) { if (targets[i].name == _lastTouched[id][key].obj.name) { found = true; break; } } //If is not in the targets object we fire the TOUCH_OUT event if (found == false) { _lastTouched[id][key] = {bool:false,obj:_lastTouched[id][key].obj}; local = _lastTouched[id][key].obj.parent.globalToLocal(new Point(point.x,point.y)); _lastTouched[id][key].obj.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,true,false,0,false,local.x,local.y)); } } } //We look now into the targets object for (i = 0,max = targets.length; i < max; i++) { var item:DisplayObject = targets[i]; local = item.parent.globalToLocal(new Point(point.x,point.y)); //if the object is new (was not in the lastTouched array OR the TOUCH_OVER is not already fired we fire TOUCH_OVER event if (! _lastTouched[id][item.name] || _lastTouched[id][item.name].bool !== true) { _lastTouched[id][item.name] = {bool:true,obj:item}; item.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,true,false,0,false,local.x,local.y)); } } } public static function getHorizontalBlobs(r : BitmapData) : Array { if (_registerId >= 10000) _registerId = 1; var blobs : Array = []; var step : int = as3kinect.HORIZONTAL_BLOBS_SEARCH_STEP_WIDTH; var rect : Rectangle; var sourceBitmap : Bitmap = new Bitmap(r); var processingBmp : BitmapData = new BitmapData(sourceBitmap.width, sourceBitmap.height); var colorRect : Rectangle; var blobBeginnPos : int; var foundBlob : Boolean = false; var pt : Point = new Point(0, 0); var sensitivity : int = as3kinect.HORIZONTAL_BLOBS_SEARCH_SENSIVITY; for (var i : int = 0; i < r.width; i += step) { rect = new Rectangle(i, 0, step, sourceBitmap.height); processingBmp = new BitmapData(step, r.height); processingBmp.copyPixels(r, rect, pt); colorRect = processingBmp.getColorBoundsRect(0xFFFFFF, 0x000000, false); if (colorRect.height >= sensitivity) { if (!foundBlob) blobBeginnPos = i; foundBlob = true; } if (colorRect.height < sensitivity && foundBlob) { if (i - blobBeginnPos >= 3 * step) { blobs.push({x1:blobBeginnPos, x2:i}); } foundBlob = false; } } var xx : Number; var yy : Number; for (var j : int = 0; j < blobs.length; j++) { xx = int(blobs[j].x1 + (blobs[j].x2 - blobs[j].x1) / 2); yy = HEXtoRGB(r.getPixel(xx, 0))[1]; blobs[j] = new PointWithID(xx, yy); translatePosition(blobs[j]); } if (blobs.length > 0) checkBlobsIfRegistered(blobs); else _registeredBlobs = []; return _registeredBlobs; } private static function checkBlobsIfRegistered(blobs : Array) : void { var tolerance : int = as3kinect.HORIZONTAL_BLOBS_HOLD_TOLERANCE; var xIsInTolerance : Boolean = false; var yIsInTolerance : Boolean = false; var tempRegisteredBlobs : Array = []; for (var i : int = 0; i < blobs.length; i++) { xIsInTolerance = false; yIsInTolerance = false; if (_registeredBlobs.length == 0) { blobs[i].id = _registerId; tempRegisteredBlobs.push(blobs[i]); _registerId++; } else { for (var j : int = 0; j < _registeredBlobs.length; j++) { xIsInTolerance = blobs[i].x - _registeredBlobs[j].x <= tolerance && _registeredBlobs[j].x - blobs[i].x <= tolerance; yIsInTolerance = blobs[i].y - _registeredBlobs[j].y <= tolerance && _registeredBlobs[j].y - blobs[i].y <= tolerance; if (xIsInTolerance && yIsInTolerance) { blobs[i].id = _registeredBlobs[j].id; blobs[i].inUse = _registeredBlobs[j].inUse; tempRegisteredBlobs.push(blobs[i]); break; } else { if (j == _registeredBlobs.length - 1) { blobs[i].id = _registerId; tempRegisteredBlobs.push(blobs[i]); _registerId++; break; } } } } } _registeredBlobs = tempRegisteredBlobs; } private static function HEXtoRGB(hex : int) : Array { var alpha : int = hex >> 24 & 0xFF; var red : int = hex >> 16 & 0xFF; var green : int = hex >> 8 & 0xFF; var blue : int = hex & 0xFF; var rgb : Array = [alpha, red, green, blue]; return rgb; } public static function translatePosition(p : Point) : void { if (_cParams.calibrationComplete) { var str : String = "p.x= " + p.x + " p.y= " + p.y; var yf : Number = int((1 - ((p.y - _cParams.yOffset) * 0.01)) * 100) * 0.01; p.y = _cParams.screenHeight - ((p.y - _cParams.yOffset) * _cParams.yScreenFactor); var xOff : Number = int((_cParams.xOffsetTop + _cParams.xOffsetDifference * yf) * 100) * 0.01; var xFact : Number = int((_cParams.xScreenFactorTop + _cParams.xScreenFactorDifference * yf) * 100) * 0.01; p.x = (p.x - xOff) * xFact; str += " new p.x= " + p.x + " p.y= " + p.y; } else { p.y = p.y * -1; } } static public function set calibrationParams(calibrationParams : as3kinectCalibrationParams) : void { as3kinectUtils._cParams = calibrationParams; } static public function get calibrationParams() : as3kinectCalibrationParams { return _cParams; } static public function get registeredBlobs() : Array { return _registeredBlobs; } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectVideo.as000077500000000000000000000063211264163024100262250ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import org.as3kinect.as3kinect; import org.as3kinect.as3kinectSocket; import flash.utils.ByteArray; import flash.display.BitmapData; public class as3kinectVideo { private var _socket:as3kinectSocket; private var _data:ByteArray; private var _video_busy:Boolean; private var _is_mirrored:Boolean; private var _compression:int; public var bitmap:BitmapData; public function as3kinectVideo(){ _socket = as3kinectSocket.instance; _data = new ByteArray; _video_busy = false; _is_mirrored = false; _compression = 80; bitmap = new BitmapData(as3kinect.IMG_WIDTH, as3kinect.IMG_HEIGHT, false, 0xFF000000); } /* * Tell server to send the latest video frame * Note: We should lock the command while we are waiting for the data to avoid lag */ public function getBuffer():void { if(!_video_busy) { _video_busy = true; _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.GET_VIDEO); _data.writeInt(0); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Data was not complete'); } } } public function set busy(flag:Boolean):void { _video_busy = flag; } public function get busy():Boolean { return _video_busy; } public function set mirrored(flag:Boolean):void { _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.MIRROR_VIDEO); _data.writeInt(int(flag)); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Depth: Cannot change mirror state'); } else { _is_mirrored = flag; } } public function get mirrored():Boolean { return _is_mirrored; } public function set compression(quality:int):void { _data.clear(); _data.writeByte(as3kinect.CAMERA_ID); _data.writeByte(as3kinect.VIDEO_COMPRESSION); _data.writeInt(int(quality)); if(_socket.sendCommand(_data) != as3kinect.SUCCESS){ throw new Error('Depth: Cannot change depth compression'); } else { _compression = quality; } } public function get compression():int { return _compression; } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectWrapper.as000077500000000000000000000100151264163024100265720ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect { import org.as3kinect.as3kinect; import org.as3kinect.as3kinectSocket; import org.as3kinect.as3kinectMotor; import org.as3kinect.as3kinectUI; import org.as3kinect.events.as3kinectSocketEvent; import org.as3kinect.events.as3kinectWrapperEvent; import flash.utils.ByteArray; import flash.geom.Rectangle; import flash.events.EventDispatcher; public class as3kinectWrapper extends EventDispatcher { private var _socket :as3kinectSocket; private var _data :ByteArray; private var _video_waiting :Boolean = false; private var user_id :Number; private var _tracked_users :Array; public var motor:as3kinectMotor; public var depth:as3kinectDepth; public var video:as3kinectVideo; //public var ui:as3kinectUI; public function as3kinectWrapper() { /* Init motor, depth, video and UI objects */ motor = new as3kinectMotor; depth = new as3kinectDepth; video = new as3kinectVideo; //ui = new as3kinectUI(this); /* Init socket objects */ _socket = as3kinectSocket.instance; _socket.connect(as3kinect.SERVER_IP, as3kinect.SOCKET_PORT); _socket.addEventListener(as3kinectSocketEvent.ONDATA, dataReceived); /* Init data out buffer */ _data = new ByteArray(); } /* * dataReceived from socket (Protocol definition) * Metadata comes in the first and second value of the data object * first: * 0 -> Camera data * second: * 0 -> Depth ARGB received * 1 -> Video ARGB received * 1 -> Motor data * 2 -> Microphone data * 3 -> Server data * second: * 0 -> Debug info received * */ private function dataReceived(event:as3kinectSocketEvent):void{ // Send ByteArray to position 0 event.data.buffer.position = 0; switch (event.data.first) { case 0: //Camera switch (event.data.second) { case 0: //Depth received dispatchEvent(new as3kinectWrapperEvent(as3kinectWrapperEvent.ON_DEPTH, event.data.buffer)); depth.busy = false; break; case 1: //Raw Depth received dispatchEvent(new as3kinectWrapperEvent(as3kinectWrapperEvent.ON_RAW_DEPTH, event.data.buffer)); depth.busy = false; break; case 2: //Video received dispatchEvent(new as3kinectWrapperEvent(as3kinectWrapperEvent.ON_VIDEO, event.data.buffer)); video.busy = false; break; } break; case 1: //Motor switch (event.data.second) { case 2: //Accelerometer received motor.updateDataFromBytes(event.data.buffer); dispatchEvent(new as3kinectWrapperEvent(as3kinectWrapperEvent.ON_ACCELEROMETER, motor.data)); motor.busy = false; break; } break; case 2: //Mic break; case 3: //Server switch (event.data.second) { case 0: //Debug received //if(_debugging) _console.appendText(event.data.buffer.toString()); break; } break; } // Clear ByteArray after used event.data.buffer.clear(); } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/as3kinectWrapperEvent.as000077500000000000000000000032271264163024100276030ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect.events { import flash.events.Event; import flash.sampler.StackFrame; public class as3kinectWrapperEvent extends Event { public static const ON_DEPTH:String = "ON_DEPTH"; public static const ON_RAW_DEPTH:String = "ON_RAW_DEPTH"; public static const ON_DEBUG:String = "ON_DEBUG"; public static const ON_VIDEO:String = "ON_VIDEO"; public static const ON_ACCELEROMETER:String = "ON_ACCELEROMETER"; public var data:*; public function as3kinectWrapperEvent(type:String, data:*) { this.data = data; super(type); } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/events/000077500000000000000000000000001264163024100243245ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/events/as3kinectCalibrationEvent.as000066400000000000000000000006711264163024100317130ustar00rootroot00000000000000package org.as3kinect.events { import flash.events.Event; public class as3kinectCalibrationEvent extends Event { public static const CALIBRATION_STEP_ONE:String = "CALIBRATION_FIRST_STEP_as3kinectCalibrationEvent"; public static const CALIBRATION_COMPLETE:String = "CALIBRATION_COMPLETE_as3kinectCalibrationEvent"; public function as3kinectCalibrationEvent(type : String) { super(type); } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/events/as3kinectSocketEvent.as000077500000000000000000000027571264163024100307260ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect.events { import flash.events.Event; public class as3kinectSocketEvent extends Event { public static const ONCONNECT:String = "ONCONNECT"; public static const ONDATA:String = "ONDATA"; public static const ONERROR:String = "ONERROR"; public var data:*; public function as3kinectSocketEvent(type:String, data:*) { this.data = data; super(type); } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/events/as3kinectWrapperEvent.as000077500000000000000000000032271264163024100311070ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect.events { import flash.events.Event; import flash.sampler.StackFrame; public class as3kinectWrapperEvent extends Event { public static const ON_DEPTH:String = "ON_DEPTH"; public static const ON_RAW_DEPTH:String = "ON_RAW_DEPTH"; public static const ON_DEBUG:String = "ON_DEBUG"; public static const ON_VIDEO:String = "ON_VIDEO"; public static const ON_ACCELEROMETER:String = "ON_ACCELEROMETER"; public var data:*; public function as3kinectWrapperEvent(type:String, data:*) { this.data = data; super(type); } } }libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/objects/000077500000000000000000000000001264163024100244515ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/objects/PointWithID.as000066400000000000000000000005401264163024100271370ustar00rootroot00000000000000package org.as3kinect.objects { import flash.geom.Point; /** * @author stevie * @date 24.06.2011 */ public class PointWithID extends Point { public var id:int; public var inUse:Boolean; public function PointWithID(x : Number = 0, y : Number = 0) { super(x, y); } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/objects/as3kinectCalibrationParams.as000066400000000000000000000026051264163024100322010ustar00rootroot00000000000000package org.as3kinect.objects { /** * @author stevie * @date 29.06.2011 */ public class as3kinectCalibrationParams { public var screenHeight : int = 0; public var screenWidth : int = 0; public var xOffsetTop : Number; public var xOffsetDifference : Number; public var xScreenFactorTop : Number; public var xScreenFactorDifference : Number; public var yOffset : Number; public var yScreenFactor : Number; public var sliceRectY : Number = 0; public var sliceRectHeight : Number = 20; public var calibrationComplete : Boolean; public function toString() : String{ var str : String = "screenHeight: " + screenHeight + "\n"; str += "screenHeight: " + screenHeight + "\n"; str += "screenWidth: " + screenWidth + "\n"; str += "xOffsetTop: " + xOffsetTop + "\n"; str += "xOffsetDifference: " + xOffsetDifference + "\n"; str += "xScreenFactorTop: " + xScreenFactorTop + "\n"; str += "xScreenFactorDifference: " + xScreenFactorDifference + "\n"; str += "yOffset: " + yOffset + "\n"; str += "yScreenFactor: " + yScreenFactor + "\n"; str += "sliceRectY: " + sliceRectY + "\n"; str += "slicsliceRectHeighteRectY: " + sliceRectHeight + "\n"; return str; } } } libfreenect-0.5.3/wrappers/actionscript/org/as3kinect/objects/motorData.as000077500000000000000000000026771264163024100267470ustar00rootroot00000000000000/* * * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL20 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, * you may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or * 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * Binary distributions must follow the binary distribution requirements of * either License. * */ package org.as3kinect.objects { public class motorData { public var ax : uint; public var ay : uint; public var az : uint; public var dx : Number; public var dy : Number; public var dz : Number; public function motorData() { this.ax = 0; this.ay = 0; this.az = 0; this.dx = 0; this.dy = 0; this.dz = 0; } } } libfreenect-0.5.3/wrappers/actionscript/server/000077500000000000000000000000001264163024100216535ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/actionscript/server/as3-server.c000077500000000000000000000261111264163024100240150ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #ifndef _WIN32 #include #include #else #include #include #pragma comment(lib, "Ws2_32.lib") #include #include unsigned sleep(unsigned seconds) { Sleep(seconds*1000); // The Windows Sleep operates on milliseconds return(0); } #endif #include #include "libfreenect_sync.h" #include "libfreenect.h" #include #include #include "freenect_network.h" #include "as3_jpeg.h" #include "libfreenect_sync.h" int g_argc; char **g_argv; char *_current_version = "v0.9c"; pthread_t connection_thread; #define AS3_BITMAPDATA_LEN 640 * 480 * 4 uint8_t buf_depth[AS3_BITMAPDATA_LEN]; uint8_t buf_rgb[AS3_BITMAPDATA_LEN]; void *buf_depth_temp; void *buf_rgb_temp; int die = 0; int psent = 0; int _video_mirrored = 0, _depth_mirrored = 0, _min_depth = 600, _max_depth = 800, _video_compression = 80, _depth_compression = 20; int client_connected = 0; #ifdef _WIN32 unsigned sleep(unsigned seconds) { Sleep(seconds*1000); // The Windows Sleep operates on milliseconds return(0); } #endif void send_policy_file(int child){ /*if(psent == 0){ char * str = "\n"; #ifdef WIN32 int n = send(data_client_socket, (char*)str, 235, 0); #else int n = write(child,str , 235); #endif if ( n < 0 || n != 235) { fprintf(stderr, "Error on write() for policy (%d instead of %d)\n",n, 235); } //psent = 1; }*/ } //send depth ARGB to client void sendDepth(){ int n; uint32_t ts, x, y, i, j; freenect_sync_get_depth(&buf_depth_temp, &ts, 0, FREENECT_DEPTH_11BIT); uint16_t *depth = (uint16_t*) buf_depth_temp; freenect_frame_mode depth_mode = freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT); //uint16_t *tmp_depth = (uint16_t*) malloc(FREENECT_DEPTH_11BIT_SIZE); uint16_t *tmp_depth = (uint16_t*) malloc(depth_mode.bytes); if(_depth_mirrored){ //MIRROR DEPTH DATA for(x = 0; x < depth_mode.width; x++){ for(y = 0; y < depth_mode.height; y++){ i = x + (y * depth_mode.width); j = (depth_mode.width - x - 1) + (y * depth_mode.width); tmp_depth[i] = depth[j]; } } depth = tmp_depth; } for (i=0; i< depth_mode.width * depth_mode.height; i++) { if(_depth_compression != 0) { buf_depth[3 * i + 0] = 0x00; buf_depth[3 * i + 1] = 0x00; buf_depth[3 * i + 2] = 0x00; } else { buf_depth[4 * i + 0] = 0x00; buf_depth[4 * i + 1] = 0x00; buf_depth[4 * i + 2] = 0x00; buf_depth[4 * i + 3] = 0xFF; } if(depth[i] < _max_depth && depth[i] > _min_depth){ unsigned char l = 0xFF - ((depth[i] - _min_depth) & 0xFF); if(_depth_compression != 0) { buf_depth[3 * i + 0] = l; buf_depth[3 * i + 1] = l; buf_depth[3 * i + 2] = l; } else { buf_depth[4 * i + 0] = l; buf_depth[4 * i + 1] = l; buf_depth[4 * i + 2] = l; buf_depth[4 * i + 3] = 0xFF; } } } if(_depth_compression != 0) { unsigned char *compressed_buff = (unsigned char *)malloc(AS3_BITMAPDATA_LEN); unsigned long len = 0; RGB_2_JPEG(buf_depth, &compressed_buff, &len, _depth_compression); n = freenect_network_sendMessage(0, 0, compressed_buff, (int)len); free(compressed_buff); } else { n = freenect_network_sendMessage(0, 0, buf_depth, AS3_BITMAPDATA_LEN); } if (n < 0) { printf("Error sending depth\n"); client_connected = 0; } free(tmp_depth); } //send depth ARGB to client void sendRawDepth(){ uint32_t ts, x, y, i, j; freenect_sync_get_depth(&buf_depth_temp, &ts, 0, FREENECT_DEPTH_11BIT); uint16_t *depth = (uint16_t*) buf_depth_temp; freenect_frame_mode depth_mode = freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT); uint16_t *tmp_depth = (uint16_t*) malloc(depth_mode.bytes); unsigned char *char_depth = (unsigned char *) malloc(depth_mode.bytes); if(_depth_mirrored){ //MIRROR DEPTH DATA for(x = 0; x < depth_mode.width; x++){ for(y = 0; y < depth_mode.height; y++){ i = x + (y * depth_mode.width); j = (depth_mode.width - x - 1) + (y * depth_mode.width); tmp_depth[i] = depth[j]; } } depth = tmp_depth; } for (i=0; i<640 * 480; i++) { memcpy(char_depth + (i*2), &depth[i], 2); } int n = freenect_network_sendMessage(0, 1, char_depth, depth_mode.bytes); if (n < 0) { printf("Error sending raw depth\n"); client_connected = 0; } free(char_depth); free(tmp_depth); } //send video ARGB to client void sendVideo(){ int n; uint32_t ts,x, y, i, j; freenect_sync_get_video(&buf_rgb_temp, &ts, 0, FREENECT_VIDEO_RGB); uint8_t *rgb = (uint8_t*)buf_rgb_temp; freenect_frame_mode video_mode = freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB); //MIRROR RGB DATA AND ADD ALPHA for(x = 0; x < video_mode.width; x++){ for(y = 0; y < video_mode.height; y++){ i = x + (y * video_mode.width); if(!_video_mirrored) j = i; else j = (video_mode.width - x - 1) + (y * video_mode.width); if(_video_compression != 0) { buf_rgb[3 * i + 2] = rgb[3 * j + 2]; buf_rgb[3 * i + 1] = rgb[3 * j + 1]; buf_rgb[3 * i + 0] = rgb[3 * j + 0]; } else { buf_rgb[4 * i + 0] = rgb[3 * j + 2]; buf_rgb[4 * i + 1] = rgb[3 * j + 1]; buf_rgb[4 * i + 2] = rgb[3 * j + 0]; buf_rgb[4 * i + 3] = 0x00; } } } if(_video_compression != 0) { unsigned char *compressed_buff = (unsigned char *)malloc(AS3_BITMAPDATA_LEN); unsigned long len = 0; RGB_2_JPEG(buf_rgb, &compressed_buff, &len, _video_compression); n = freenect_network_sendMessage(0, 2, compressed_buff, (int)len); free(compressed_buff); } else { n = freenect_network_sendMessage(0, 2, buf_rgb, AS3_BITMAPDATA_LEN); } if ( n < 0) { printf("Error sending Video\n"); client_connected = 0; } } //send accelerometer data to client void sendAccelerometers() { int16_t ax,ay,az; double dx,dy,dz; unsigned char buffer_send[3*2+3*8]; freenect_raw_tilt_state *state; freenect_sync_get_tilt_state(&state, 0); ax = state->accelerometer_x; ay = state->accelerometer_y; az = state->accelerometer_z; freenect_get_mks_accel(state, &dx, &dy, &dz); memcpy(&buffer_send,&ax, sizeof(int16_t)); memcpy(&buffer_send[2],&ay, sizeof(int16_t)); memcpy(&buffer_send[4],&az, sizeof(int16_t)); memcpy(&buffer_send[6],&dx, sizeof(double)); memcpy(&buffer_send[14],&dy, sizeof(double)); memcpy(&buffer_send[22],&dz, sizeof(double)); int n = freenect_network_sendMessage(1, 2, buffer_send, 3*2+3*8); if ( n < 0) { printf("Error sending Accelerometers\n"); client_connected = 0; } } //Connection protocol handler void *connection_handler(void *arg) { int value; int len = 8*10; char *buff = (char*)malloc(len); //Command buffer //send_policy_file(data_child); while(client_connected) { freenect_network_read(buff, &len); //If command length is multiple of 6 if(len > 0 && len % 6 == 0){ //Get the number of commands received int max = len / 6; int i; //For each command received for(i = 0; i < max; i++){ memcpy(&value, &buff[2 + (i*6)], sizeof(int)); value = ntohl(value); //The BIG switch (Communication protocol) switch(buff[0 + (i*6)]){ case 0: //CAMERA switch(buff[1 + (i*6)]){ case 0: //GET DEPTH sendDepth(); break; case 1: //GET RAW DEPTH sendRawDepth(); break; case 2: //GET RGB sendVideo(); break; case 3: //Mirror depth _depth_mirrored = value; break; case 4: //Mirror video _video_mirrored = value; break; case 5: //Min depth _min_depth = value; break; case 6: //Max depth _max_depth = value; break; case 7: //Depth compression _depth_compression = value; break; case 8: //Video compression _video_compression = value; break; } break; case 1: //MOTOR switch(buff[1 + (i*6)]){ case 0: //MOVE freenect_sync_set_tilt_degs(value, 0); break; case 1: //LED COLOR freenect_sync_set_led((freenect_led_options) value, 0); break; case 2: //Accelerometer sendAccelerometers(); break; } break; } } } else { //Command was not multiple of 6 (we received an invalid command) if(!die) printf("got bad command (%d)\n", len ); client_connected = 0; } } if(!die) { printf("Disconecting client...\n"); freenect_network_wait(); //waiting for client led status freenect_sync_set_led((freenect_led_options) 4, 0); } return NULL; } void server_connected(){ printf("###### Got client\n"); //got client led status freenect_sync_set_led((freenect_led_options) 1, 0); client_connected = 1; if (pthread_create(&connection_thread, NULL, &connection_handler, NULL)) { fprintf(stderr, "Error on pthread_create() for SERVER\n"); } } //Called when C-c or C-z is pressed #ifdef _WIN32 void clean_exit(int){ die = 1; } #else void clean_exit(){ printf("clean exit called\n"); die = 1; freenect_network_close(); } #endif //Main: we start here int main(int argc, char **argv) { printf("as3kinect server %s\n", _current_version); //waiting for client led status freenect_sync_set_led((freenect_led_options) 4, 0); //Listening to C-c if (signal (SIGINT, clean_exit) == SIG_IGN) signal (SIGINT, SIG_IGN); //Listening to C-z #ifndef _WIN32 if (signal (SIGTSTP, clean_exit) == SIG_IGN) signal (SIGTSTP, SIG_IGN); #endif //Alloc memory for video and depth frames buf_depth_temp = malloc(FREENECT_DEPTH_11BIT); buf_rgb_temp = malloc(FREENECT_VIDEO_RGB); //Initialize network socket if ( freenect_network_init(server_connected) < 0 ) die = 1; //Sleep main process until exit while(!die) sleep(2); //making a clean exit free(buf_depth_temp); free(buf_rgb_temp); //device off led status freenect_sync_set_led((freenect_led_options) 0, 0); freenect_sync_stop(); printf("\n[as3-server] cleanup done!\n"); return 0; } libfreenect-0.5.3/wrappers/actionscript/server/as3_jpeg.c000077500000000000000000000037351264163024100235250ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "as3_jpeg.h" /* * Compress RGB buffer in memory */ int RGB_2_JPEG(unsigned char *buffer, unsigned char **compressed, long unsigned int *new_len, int quality) { struct jpeg_compress_struct cinfo = {0}; struct jpeg_error_mgr jerr; JSAMPROW row_ptr[1]; int row_stride; *compressed = NULL; *new_len = 0; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, compressed, new_len); cinfo.image_width = 640; cinfo.image_height = 480; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); row_stride = 640 * 3; while (cinfo.next_scanline < cinfo.image_height) { row_ptr[0] = &buffer[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_ptr, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return 1; }libfreenect-0.5.3/wrappers/actionscript/server/as3_jpeg.h000077500000000000000000000025101264163024100235200ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #ifdef __cplusplus extern "C" { #endif #include #include #include int RGB_2_JPEG(unsigned char *buffer, unsigned char **compressed, long unsigned int *new_len, int quality); #ifdef __cplusplus } #endif libfreenect-0.5.3/wrappers/actionscript/server/freenect_network.c000077500000000000000000000134061264163024100253720ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "freenect_network.h" int data_child; int closing = 0; #ifdef WIN32 struct addrinfo si_data; PCSTR conf_port_data = "6001"; SOCKET data_socket = INVALID_SOCKET, data_client_socket = INVALID_SOCKET; #else struct sockaddr_in si_data; char *conf_ip = "127.0.0.1"; int s_data = -1, conf_port_data = 6001; #endif callback freenect_network_connected; //Init network int freenect_network_init(callback cb) { #ifndef _WIN32 //Init server UNIX signal(SIGPIPE, SIG_IGN); freenect_network_initSocket(si_data, conf_port_data, &s_data); #else //Init server Winsock (Windows) WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { printf("WSAStartup failed with error: %d\n", err); return 1; } freenect_network_initSocket(si_data, conf_port_data, &data_socket); #endif freenect_network_connected = cb; freenect_network_wait(); return 0; } void freenect_network_read(char *buff, int *len){ int n; #ifdef _WIN32 //Listen for data (Winsock) n = recv(data_client_socket, buff, *len, 0); #else //Listen for data (UNIX) n = read(data_child, buff, *len); #endif *len = n; } // Send Message with two bytes as metadata and pkg len as the 3rd byte int freenect_network_sendMessage(int first, int second, unsigned char *data, int len) { int n; int m_len = 1 + 1 + sizeof(int); unsigned char *msg = (unsigned char*) malloc(m_len + len); memcpy(msg, &first, 1); memcpy(msg + 1, &second, 1); memcpy(msg + 2, &len, sizeof(int)); memcpy(msg + m_len, data, len); #ifdef WIN32 n = send(data_client_socket, (char*)msg, m_len + len, 0); #else n = write(data_child, msg, m_len + len); #endif free((void*)msg); return n; } //Waiting for a client to connect void freenect_network_wait() { int childlen; struct sockaddr_in childaddr; childlen = sizeof(childaddr); printf("### Wait client\n"); #ifdef _WIN32 //Wait for connection (Winsock) data_client_socket = accept(data_socket, NULL, NULL); if (data_client_socket == INVALID_SOCKET) { if(!closing) printf("Error on accept() for data, exit data thread. %d\n", WSAGetLastError()); closesocket(data_socket); WSACleanup(); } #else //Wait for connection (UNIX) data_child = accept(s_data, (struct sockaddr *)&childaddr, (unsigned int *)&childlen); if ( data_child < 0 ) { if(!closing) fprintf(stderr, "Error on accept() for data, exit data thread.\n"); } #endif //callback if(!closing) freenect_network_connected(); } //Close network socket void freenect_network_close() { closing = 1; #ifdef _WIN32 if ( data_socket != INVALID_SOCKET ) closesocket(data_socket); #else if ( s_data != -1 ) close(s_data), s_data = -1; #endif } #ifdef _WIN32 int freenect_network_initSocket(struct addrinfo si_type, PCSTR conf_port, SOCKET *the_socket){ struct addrinfo *result = NULL; int iResult; ZeroMemory(&si_type, sizeof (si_type)); si_type.ai_family = AF_INET; si_type.ai_socktype = SOCK_STREAM; si_type.ai_protocol = IPPROTO_TCP; si_type.ai_flags = AI_PASSIVE; iResult = getaddrinfo(NULL, conf_port, &si_type, &result); if (iResult != 0) { printf("Socket: getaddrinfo failed: %d\n", iResult); WSACleanup(); return 1; } *the_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (*the_socket == INVALID_SOCKET) { printf("Socket: socket failed [%ld]\n", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } iResult = bind(*the_socket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("Socket: bind failed: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(*the_socket); WSACleanup(); return 1; } freeaddrinfo(result); if ( listen(*the_socket, SOMAXCONN ) == SOCKET_ERROR ) { printf( "Socket: listen failed [%ld]\n", WSAGetLastError() ); closesocket(*the_socket); WSACleanup(); return 1; } return 0; } #else int freenect_network_initSocket(struct sockaddr_in si_type, int conf_port, int *the_socket) { int optval = 1; if ( (*the_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) { fprintf(stderr, "Unable to create depth socket\n"); return -1; } setsockopt(*the_socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(optval)); memset((char *) &si_type, 0, sizeof(si_type)); si_type.sin_family = AF_INET; si_type.sin_port = htons(conf_port); si_type.sin_addr.s_addr = inet_addr(conf_ip); if ( bind(*the_socket, (struct sockaddr *)&si_type, sizeof(si_type)) < 0 ) { fprintf(stderr, "Error at bind() for depth\n"); return -1; } if ( listen(*the_socket, 1) < 0 ) { fprintf(stderr, "Error on listen() for depth\n"); return -1; } return 0; } #endiflibfreenect-0.5.3/wrappers/actionscript/server/freenect_network.h000077500000000000000000000037061264163024100254010ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #ifdef __cplusplus extern "C" { #endif #include #include #ifndef _WIN32 #include #include #else #include #include #pragma comment(lib, "Ws2_32.lib") #include #include #endif #include #include #include typedef void (*callback)(void); int freenect_network_init(callback cb); void freenect_network_close(); void freenect_network_read(char *buff, int *len); int freenect_network_sendMessage(int first, int second, unsigned char *data, int len); void freenect_network_wait(); #ifdef _WIN32 int freenect_network_initSocket(struct addrinfo si_type, PCSTR conf_port, SOCKET *the_socket); #else int freenect_network_initSocket(struct sockaddr_in si_type, int conf_port, int *the_socket); #endif #ifdef __cplusplus } #endif libfreenect-0.5.3/wrappers/c_sync/000077500000000000000000000000001264163024100171215ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/c_sync/CMakeLists.txt000066400000000000000000000020031264163024100216540ustar00rootroot00000000000000###################################################################################### # C Synchronous Interface ###################################################################################### set(THREADS_USE_PTHREADS_WIN32 true) find_package(Threads REQUIRED) include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) add_library (freenect_sync SHARED libfreenect_sync.c) add_library (freenect_sync_static STATIC libfreenect_sync.c) set_target_properties (freenect_sync_static PROPERTIES OUTPUT_NAME freenect_sync) set_target_properties (freenect_sync PROPERTIES VERSION ${PROJECT_VER} SOVERSION ${PROJECT_APIVER}) target_link_libraries (freenect_sync freenect ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (freenect_sync_static freenect ${CMAKE_THREAD_LIBS_INIT}) install (TARGETS freenect_sync DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}") install (TARGETS freenect_sync_static DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}") install (FILES "libfreenect_sync.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) libfreenect-0.5.3/wrappers/c_sync/README000066400000000000000000000006171264163024100200050ustar00rootroot00000000000000** Freenect C Synchronous Interface ** - Brandyn White (bwhite@dappervision.com) - Andrew Miller (amiller@dappervision.com) Provides a synchronous interface (e.g., freenect_get_depth and freenect_get_rgb) as opposed to callbacks. Uses pthreads. The Cython Syncrhonous interfaces uses these, that is the simplest way to test this. See http://openkinect.org/wiki/C_Sync_Wrapper for up-to-date infolibfreenect-0.5.3/wrappers/c_sync/libfreenect_sync.c000066400000000000000000000321431264163024100226060ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com) * Andrew Miller (amiller@dappervision.com) * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #include #include "libfreenect_registration.h" #include "libfreenect_sync.h" typedef struct buffer_ring { pthread_mutex_t lock; pthread_cond_t cb_cond; void *bufs[3]; uint32_t timestamp; int valid; // True if middle buffer is valid int fmt; int res; } buffer_ring_t; typedef struct sync_kinect { freenect_device *dev; buffer_ring_t video; buffer_ring_t depth; } sync_kinect_t; typedef int (*set_buffer_t)(freenect_device *dev, void *buf); #define MAX_KINECTS 64 static sync_kinect_t *kinects[MAX_KINECTS] = { 0 }; static freenect_context *ctx; static int thread_running = 0; static pthread_t thread; static pthread_mutex_t runloop_lock = PTHREAD_MUTEX_INITIALIZER; static int pending_runloop_tasks = 0; static pthread_mutex_t pending_runloop_tasks_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t pending_runloop_tasks_cond = PTHREAD_COND_INITIALIZER; /* Locking Convention Rules: - if you need more than one lock on a line, get them from left to right - do not mix locks on different lines - if you need to change the lock rules, make sure you check everything and update this Lock Families: - pending_runloop_tasks_lock - runloop_lock, buffer_ring_t.lock (NOTE: You may only have one) */ static int alloc_buffer_ring_video(freenect_resolution res, freenect_video_format fmt, buffer_ring_t *buf) { int sz, i; switch (fmt) { case FREENECT_VIDEO_RGB: case FREENECT_VIDEO_BAYER: case FREENECT_VIDEO_IR_8BIT: case FREENECT_VIDEO_IR_10BIT: case FREENECT_VIDEO_IR_10BIT_PACKED: sz = freenect_find_video_mode(res, fmt).bytes; break; default: printf("Invalid video format %d\n", fmt); return -1; } for (i = 0; i < 3; ++i) buf->bufs[i] = malloc(sz); buf->timestamp = 0; buf->valid = 0; buf->fmt = fmt; buf->res = res; return 0; } static int alloc_buffer_ring_depth(freenect_resolution res, freenect_depth_format fmt, buffer_ring_t *buf) { int sz, i; switch (fmt) { case FREENECT_DEPTH_11BIT: case FREENECT_DEPTH_10BIT: case FREENECT_DEPTH_11BIT_PACKED: case FREENECT_DEPTH_10BIT_PACKED: case FREENECT_DEPTH_REGISTERED: case FREENECT_DEPTH_MM: sz = freenect_find_depth_mode(res, fmt).bytes; break; default: printf("Invalid depth format %d\n", fmt); return -1; } for (i = 0; i < 3; ++i) buf->bufs[i] = malloc(sz); buf->timestamp = 0; buf->valid = 0; buf->fmt = fmt; buf->res = res; return 0; } static void free_buffer_ring(buffer_ring_t *buf) { int i; for (i = 0; i < 3; ++i) { free(buf->bufs[i]); buf->bufs[i] = NULL; } buf->timestamp = 0; buf->valid = 0; buf->fmt = -1; buf->res = -1; } static void producer_cb_inner(freenect_device *dev, void *data, uint32_t timestamp, buffer_ring_t *buf, set_buffer_t set_buffer) { pthread_mutex_lock(&buf->lock); assert(data == buf->bufs[2]); void *temp_buf = buf->bufs[1]; buf->bufs[1] = buf->bufs[2]; buf->bufs[2] = temp_buf; set_buffer(dev, temp_buf); buf->timestamp = timestamp; buf->valid = 1; pthread_cond_signal(&buf->cb_cond); pthread_mutex_unlock(&buf->lock); } static void video_producer_cb(freenect_device *dev, void *data, uint32_t timestamp) { producer_cb_inner(dev, data, timestamp, &((sync_kinect_t *)freenect_get_user(dev))->video, freenect_set_video_buffer); } static void depth_producer_cb(freenect_device *dev, void *data, uint32_t timestamp) { producer_cb_inner(dev, data, timestamp, &((sync_kinect_t *)freenect_get_user(dev))->depth, freenect_set_depth_buffer); } /* You should only use these functions to manipulate the pending_runloop_tasks_lock*/ static void pending_runloop_tasks_inc(void) { pthread_mutex_lock(&pending_runloop_tasks_lock); assert(pending_runloop_tasks >= 0); ++pending_runloop_tasks; pthread_mutex_unlock(&pending_runloop_tasks_lock); } static void pending_runloop_tasks_dec(void) { pthread_mutex_lock(&pending_runloop_tasks_lock); --pending_runloop_tasks; assert(pending_runloop_tasks >= 0); if (!pending_runloop_tasks) pthread_cond_signal(&pending_runloop_tasks_cond); pthread_mutex_unlock(&pending_runloop_tasks_lock); } static void pending_runloop_tasks_wait_zero(void) { pthread_mutex_lock(&pending_runloop_tasks_lock); while (pending_runloop_tasks) pthread_cond_wait(&pending_runloop_tasks_cond, &pending_runloop_tasks_lock); pthread_mutex_unlock(&pending_runloop_tasks_lock); } static void *init(void *unused) { pending_runloop_tasks_wait_zero(); pthread_mutex_lock(&runloop_lock); while (thread_running && freenect_process_events(ctx) >= 0) { pthread_mutex_unlock(&runloop_lock); // NOTE: This lets you run tasks while process_events isn't running pending_runloop_tasks_wait_zero(); pthread_mutex_lock(&runloop_lock); } // Go through each device, call stop video, close device int i; for (i = 0; i < MAX_KINECTS; ++i) { if (kinects[i]) { freenect_stop_video(kinects[i]->dev); freenect_stop_depth(kinects[i]->dev); freenect_set_user(kinects[i]->dev, NULL); freenect_close_device(kinects[i]->dev); free_buffer_ring(&kinects[i]->video); free_buffer_ring(&kinects[i]->depth); free(kinects[i]); kinects[i] = NULL; } } freenect_shutdown(ctx); pthread_mutex_unlock(&runloop_lock); return NULL; } static void init_thread(void) { thread_running = 1; freenect_init(&ctx, 0); // We claim both the motor and the camera, because we can't know in advance // which devices the caller will want, and the c_sync interface doesn't // support audio, so there's no reason to claim the device needlessly. freenect_select_subdevices(ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); pthread_create(&thread, NULL, init, NULL); } static int change_video_format(sync_kinect_t *kinect, freenect_resolution res, freenect_video_format fmt) { freenect_stop_video(kinect->dev); free_buffer_ring(&kinect->video); if (alloc_buffer_ring_video(res, fmt, &kinect->video)) return -1; freenect_set_video_mode(kinect->dev, freenect_find_video_mode(res, fmt)); freenect_set_video_buffer(kinect->dev, kinect->video.bufs[2]); freenect_start_video(kinect->dev); return 0; } static int change_depth_format(sync_kinect_t *kinect, freenect_resolution res, freenect_depth_format fmt) { freenect_stop_depth(kinect->dev); free_buffer_ring(&kinect->depth); if (alloc_buffer_ring_depth(res, fmt, &kinect->depth)) return -1; freenect_set_depth_mode(kinect->dev, freenect_find_depth_mode(res, fmt)); freenect_set_depth_buffer(kinect->dev, kinect->depth.bufs[2]); freenect_start_depth(kinect->dev); return 0; } static sync_kinect_t *alloc_kinect(int index) { sync_kinect_t *kinect = (sync_kinect_t*)malloc(sizeof(sync_kinect_t)); if (freenect_open_device(ctx, &kinect->dev, index)) { free(kinect); return NULL; } int i; for (i = 0; i < 3; ++i) { kinect->video.bufs[i] = NULL; kinect->depth.bufs[i] = NULL; } kinect->video.fmt = -1; kinect->video.res = -1; kinect->depth.fmt = -1; kinect->depth.res = -1; freenect_set_video_callback(kinect->dev, video_producer_cb); freenect_set_depth_callback(kinect->dev, depth_producer_cb); pthread_mutex_init(&kinect->video.lock, NULL); pthread_mutex_init(&kinect->depth.lock, NULL); pthread_cond_init(&kinect->video.cb_cond, NULL); pthread_cond_init(&kinect->depth.cb_cond, NULL); return kinect; } static int setup_kinect(int index, int res, int fmt, int is_depth) { pending_runloop_tasks_inc(); pthread_mutex_lock(&runloop_lock); int thread_running_prev = thread_running; if (!thread_running) init_thread(); if (!kinects[index]) { kinects[index] = alloc_kinect(index); } if (!kinects[index]) { printf("Error: Invalid index [%d]\n", index); // If we started the thread, we need to bring it back if (!thread_running_prev) { thread_running = 0; pthread_mutex_unlock(&runloop_lock); pending_runloop_tasks_dec(); pthread_join(thread, NULL); } else { pthread_mutex_unlock(&runloop_lock); pending_runloop_tasks_dec(); } return -1; } freenect_set_user(kinects[index]->dev, kinects[index]); buffer_ring_t *buf; if (is_depth) buf = &kinects[index]->depth; else buf = &kinects[index]->video; pthread_mutex_lock(&buf->lock); if ((buf->fmt != fmt) || (buf->res != res)) { if (is_depth) change_depth_format(kinects[index], (freenect_resolution)res, (freenect_depth_format)fmt); else change_video_format(kinects[index], (freenect_resolution)res, (freenect_video_format)fmt); } pthread_mutex_unlock(&buf->lock); pthread_mutex_unlock(&runloop_lock); pending_runloop_tasks_dec(); return 0; } static int sync_get(void **data, uint32_t *timestamp, buffer_ring_t *buf) { pthread_mutex_lock(&buf->lock); // If there isn't a frame ready for us while (!buf->valid) pthread_cond_wait(&buf->cb_cond, &buf->lock); void *temp_buf = buf->bufs[0]; *data = buf->bufs[0] = buf->bufs[1]; buf->bufs[1] = temp_buf; buf->valid = 0; *timestamp = buf->timestamp; pthread_mutex_unlock(&buf->lock); return 0; } /* Use this to make sure the runloop is locked and no one is in it. Then you can call arbitrary functions from libfreenect.h in a safe way. If the kinect with this index has not been initialized yet, then it will try to set it up. If this function is successful, then you can access kinects[index]. Don't forget to unlock the runloop when you're done. Returns 0 if successful, nonzero if kinect[index] is unvailable */ static int runloop_enter(int index) { if (index < 0 || index >= MAX_KINECTS) { printf("Error: Invalid index [%d]\n", index); return -1; } if (!thread_running || !kinects[index]) if (setup_kinect(index, FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT, 1)) return -1; pending_runloop_tasks_inc(); pthread_mutex_lock(&runloop_lock); return 0; } static void runloop_exit() { pthread_mutex_unlock(&runloop_lock); pending_runloop_tasks_dec(); } int freenect_sync_get_video_with_res(void **video, uint32_t *timestamp, int index, freenect_resolution res, freenect_video_format fmt) { if (index < 0 || index >= MAX_KINECTS) { printf("Error: Invalid index [%d]\n", index); return -1; } if (!thread_running || !kinects[index] || kinects[index]->video.fmt != fmt || kinects[index]->video.res != res) if (setup_kinect(index, res, fmt, 0)) return -1; sync_get(video, timestamp, &kinects[index]->video); return 0; } int freenect_sync_get_video(void **video, uint32_t *timestamp, int index, freenect_video_format fmt) { return freenect_sync_get_video_with_res(video, timestamp, index, FREENECT_RESOLUTION_MEDIUM, fmt); } int freenect_sync_get_depth_with_res(void **depth, uint32_t *timestamp, int index, freenect_resolution res, freenect_depth_format fmt) { if (index < 0 || index >= MAX_KINECTS) { printf("Error: Invalid index [%d]\n", index); return -1; } if (!thread_running || !kinects[index] || kinects[index]->depth.fmt != fmt || kinects[index]->depth.res != res) if (setup_kinect(index, res, fmt, 1)) return -1; sync_get(depth, timestamp, &kinects[index]->depth); return 0; } int freenect_sync_get_depth(void **depth, uint32_t *timestamp, int index, freenect_depth_format fmt) { return freenect_sync_get_depth_with_res(depth, timestamp, index, FREENECT_RESOLUTION_MEDIUM, fmt); } int freenect_sync_get_tilt_state(freenect_raw_tilt_state **state, int index) { if (runloop_enter(index)) return -1; freenect_update_tilt_state(kinects[index]->dev); *state = freenect_get_tilt_state(kinects[index]->dev); runloop_exit(); return 0; } int freenect_sync_set_tilt_degs(int angle, int index) { if (runloop_enter(index)) return -1; freenect_set_tilt_degs(kinects[index]->dev, angle); runloop_exit(); return 0; } int freenect_sync_set_led(freenect_led_options led, int index) { if (runloop_enter(index)) return -1; freenect_set_led(kinects[index]->dev, led); runloop_exit(); return 0; } int freenect_sync_camera_to_world(int cx, int cy, int wz, double* wx, double* wy, int index) { if (runloop_enter(index)) return -1; freenect_camera_to_world(kinects[index]->dev, cx, cy, wz, wx, wy); runloop_exit(); return 0; } void freenect_sync_stop(void) { if (thread_running) { thread_running = 0; pthread_join(thread, NULL); } } libfreenect-0.5.3/wrappers/c_sync/libfreenect_sync.h000066400000000000000000000115121264163024100226100ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com) * Andrew Miller (amiller@dappervision.com) * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" #include /// If Win32, export all functions for DLL usage #ifndef _WIN32 #define FREENECTAPI_SYNC /**< DLLExport information for windows, set to nothing on other platforms */ #else /**< DLLExport information for windows, set to nothing on other platforms */ #ifdef __cplusplus #define FREENECTAPI_SYNC extern "C" __declspec(dllexport) #else // this is required when building from a Win32 port of gcc without being // forced to compile all of the library files (.c) with g++... #define FREENECTAPI_SYNC __declspec(dllexport) #endif #endif #ifdef __cplusplus extern "C" { #endif FREENECTAPI_SYNC int freenect_sync_get_video_with_res(void **video, uint32_t *timestamp, int index, freenect_resolution res, freenect_video_format fmt); /* Synchronous video function, starts the runloop if it isn't running The returned buffer is valid until this function is called again, after which the buffer must not be used again. Make a copy if the data is required. Args: video: Populated with a pointer to a video buffer with a size of the requested type timestamp: Populated with the associated timestamp index: Device index (0 is the first) res: Valid resolution fmt: Valid format Returns: Nonzero on error. */ FREENECTAPI_SYNC int freenect_sync_get_video(void **video, uint32_t *timestamp, int index, freenect_video_format fmt); /* Does the exact same as above, but with a default resolution, so backwards compatibilty is maintained. The Resolution is kept at the default FREENECT_RESOLUTION_MEDIUM */ FREENECTAPI_SYNC int freenect_sync_get_depth_with_res(void **depth, uint32_t *timestamp, int index, freenect_resolution res, freenect_depth_format fmt); /* Synchronous depth function, starts the runloop if it isn't running The returned buffer is valid until this function is called again, after which the buffer must not be used again. Make a copy if the data is required. Args: depth: Populated with a pointer to a depth buffer with a size of the requested type timestamp: Populated with the associated timestamp index: Device index (0 is the first) res: Valid resolution fmt: Valid format Returns: Nonzero on error. */ FREENECTAPI_SYNC int freenect_sync_get_depth(void **depth, uint32_t *timestamp, int index, freenect_depth_format fmt); /* Again, a wrapper function to keep backward compatibility. The Resolution is kept at the default FREENECT_RESOLUTION_MEDIUM */ FREENECTAPI_SYNC int freenect_sync_set_tilt_degs(int angle, int index); /* Tilt function, starts the runloop if it isn't running Args: angle: Set the angle to tilt the device index: Device index (0 is the first) Returns: Nonzero on error. */ FREENECTAPI_SYNC int freenect_sync_get_tilt_state(freenect_raw_tilt_state **state, int index); /* Tilt state function, starts the runloop if it isn't running Args: state: Populated with an updated tilt state pointer index: Device index (0 is the first) Returns: Nonzero on error. */ FREENECTAPI_SYNC int freenect_sync_set_led(freenect_led_options led, int index); /* Led function, starts the runloop if it isn't running Args: led: The LED state to set the device to index: Device index (0 is the first) Returns: Nonzero on error. */ FREENECTAPI_SYNC int freenect_sync_camera_to_world(int cx, int cy, int wz, double* wx, double* wy, int index); /* Camera to world mapping, starts the runloop if it isn't running Wraps libfreenect_registration.h function of same name. */ FREENECTAPI_SYNC void freenect_sync_stop(void); #ifdef __cplusplus } #endif libfreenect-0.5.3/wrappers/cpp/000077500000000000000000000000001264163024100164255ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/cpp/CMakeLists.txt000066400000000000000000000014201264163024100211620ustar00rootroot00000000000000install(FILES libfreenect.hpp DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) if (BUILD_EXAMPLES) set(THREADS_USE_PTHREADS_WIN32 true) find_package(Threads REQUIRED) find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) include_directories(. ${THREADS_PTHREADS_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}) add_executable(freenect-cppview cppview.cpp) add_executable(freenect-cpp_pcview cpp_pc_view.cpp) target_link_libraries(freenect-cppview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(freenect-cpp_pcview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) install(TARGETS freenect-cppview freenect-cpp_pcview DESTINATION bin) ENDIF() libfreenect-0.5.3/wrappers/cpp/cpp_pc_view.cpp000066400000000000000000000177311264163024100214400ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include #include #include #include #if defined(__APPLE__) #include #else #include #endif class Mutex { public: Mutex() { pthread_mutex_init(&m_mutex, NULL); } void lock() { pthread_mutex_lock(&m_mutex); } void unlock() { pthread_mutex_unlock(&m_mutex); } class ScopedLock { public: ScopedLock(Mutex &mutex) : _mutex(mutex) { _mutex.lock(); } ~ScopedLock() { _mutex.unlock(); } private: Mutex &_mutex; }; private: pthread_mutex_t m_mutex; }; class MyFreenectDevice : public Freenect::FreenectDevice { public: MyFreenectDevice(freenect_context *_ctx, int _index) : Freenect::FreenectDevice(_ctx, _index), m_buffer_video(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes), m_buffer_depth(freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_REGISTERED).bytes / 2), m_new_rgb_frame(false), m_new_depth_frame(false) { setDepthFormat(FREENECT_DEPTH_REGISTERED); } // Do not call directly, even in child void VideoCallback(void *_rgb, uint32_t timestamp) { Mutex::ScopedLock lock(m_rgb_mutex); uint8_t* rgb = static_cast(_rgb); copy(rgb, rgb+getVideoBufferSize(), m_buffer_video.begin()); m_new_rgb_frame = true; } // Do not call directly, even in child void DepthCallback(void *_depth, uint32_t timestamp) { Mutex::ScopedLock lock(m_depth_mutex); uint16_t* depth = static_cast(_depth); copy(depth, depth+getDepthBufferSize()/2, m_buffer_depth.begin()); m_new_depth_frame = true; } bool getRGB(std::vector &buffer) { Mutex::ScopedLock lock(m_rgb_mutex); if (!m_new_rgb_frame) return false; buffer.swap(m_buffer_video); m_new_rgb_frame = false; return true; } bool getDepth(std::vector &buffer) { Mutex::ScopedLock lock(m_depth_mutex); if (!m_new_depth_frame) return false; buffer.swap(m_buffer_depth); m_new_depth_frame = false; return true; } private: Mutex m_rgb_mutex; Mutex m_depth_mutex; std::vector m_buffer_video; std::vector m_buffer_depth; bool m_new_rgb_frame; bool m_new_depth_frame; }; Freenect::Freenect freenect; MyFreenectDevice* device; int window(0); // Glut window identifier int mx = -1, my = -1; // Prevous mouse coordinates float anglex = 0, angley = 0; // Panning angles float zoom = 1; // Zoom factor bool color = true; // Flag to indicate to use of color in the cloud void DrawGLScene() { static std::vector rgb(640*480*3); static std::vector depth(640*480); device->getRGB(rgb); device->getDepth(depth); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPointSize(1.0f); glBegin(GL_POINTS); if (!color) glColor3ub(255, 255, 255); for (int i = 0; i < 480*640; ++i) { if (color) glColor3ub( rgb[3*i+0], // R rgb[3*i+1], // G rgb[3*i+2] ); // B float f = 595.f; // Convert from image plane coordinates to world coordinates glVertex3f( (i%640 - (640-1)/2.f) * depth[i] / f, // X = (x - cx) * d / fx (i/640 - (480-1)/2.f) * depth[i] / f, // Y = (y - cy) * d / fy depth[i] ); // Z = d } glEnd(); // Draw the world coordinate frame glLineWidth(2.0f); glBegin(GL_LINES); glColor3ub(255, 0, 0); // X-axis glVertex3f( 0, 0, 0); glVertex3f( 50, 0, 0); glColor3ub(0, 255, 0); // Y-axis glVertex3f(0, 0, 0); glVertex3f(0, 50, 0); glColor3ub(0, 0, 255); // Z-axis glVertex3f(0, 0, 0); glVertex3f(0, 0, 50); glEnd(); // Place the camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(zoom, zoom, 1); gluLookAt( -7*anglex, -7*angley, -1000.0, 0.0, 0.0, 2000.0, 0.0, -1.0, 0.0 ); glutSwapBuffers(); } void keyPressed(unsigned char key, int x, int y) { switch (key) { case 'C': case 'c': color = !color; break; case 'Q': case 'q': case 0x1B: // ESC glutDestroyWindow(window); device->stopDepth(); device->stopVideo(); exit(0); } } void mouseMoved(int x, int y) { if (mx >= 0 && my >= 0) { anglex += x - mx; angley += y - my; } mx = x; my = y; } void mouseButtonPressed(int button, int state, int x, int y) { if (state == GLUT_DOWN) { switch (button) { case GLUT_LEFT_BUTTON: mx = x; my = y; break; case 3: zoom *= 1.2f; break; case 4: zoom /= 1.2f; break; } } else if (state == GLUT_UP && button == GLUT_LEFT_BUTTON) { mx = -1; my = -1; } } void resizeGLScene(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50.0, (float)width / height, 900.0, 11000.0); glMatrixMode(GL_MODELVIEW); } void idleGLScene() { glutPostRedisplay(); } void printInfo() { std::cout << "\nAvailable Controls:" << std::endl; std::cout << "===================" << std::endl; std::cout << "Rotate : Mouse Left Button" << std::endl; std::cout << "Zoom : Mouse Wheel" << std::endl; std::cout << "Toggle Color : C" << std::endl; std::cout << "Quit : Q or Esc\n" << std::endl; } int main(int argc, char **argv) { device = &freenect.createDevice(0); device->startVideo(); device->startDepth(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(640, 480); glutInitWindowPosition(0, 0); window = glutCreateWindow("LibFreenect"); glClearColor(0.45f, 0.45f, 0.45f, 0.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); glMatrixMode(GL_PROJECTION); gluPerspective(50.0, 1.0, 900.0, 11000.0); glutDisplayFunc(&DrawGLScene); glutIdleFunc(&idleGLScene); glutReshapeFunc(&resizeGLScene); glutKeyboardFunc(&keyPressed); glutMotionFunc(&mouseMoved); glutMouseFunc(&mouseButtonPressed); printInfo(); glutMainLoop(); return 0; } libfreenect-0.5.3/wrappers/cpp/cppview.cpp000066400000000000000000000216471264163024100206200ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #include "libfreenect.hpp" #include #include #include #include #include #include #if defined(__APPLE__) #include #include #include #else #include #include #include #endif class Mutex { public: Mutex() { pthread_mutex_init( &m_mutex, NULL ); } void lock() { pthread_mutex_lock( &m_mutex ); } void unlock() { pthread_mutex_unlock( &m_mutex ); } class ScopedLock { Mutex & _mutex; public: ScopedLock(Mutex & mutex) : _mutex(mutex) { _mutex.lock(); } ~ScopedLock() { _mutex.unlock(); } }; private: pthread_mutex_t m_mutex; }; /* thanks to Yoda---- from IRC */ class MyFreenectDevice : public Freenect::FreenectDevice { public: MyFreenectDevice(freenect_context *_ctx, int _index) : Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes),m_buffer_video(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes), m_gamma(2048), m_new_rgb_frame(false), m_new_depth_frame(false) { for( unsigned int i = 0 ; i < 2048 ; i++) { float v = i/2048.0; v = std::pow(v, 3)* 6; m_gamma[i] = v*6*256; } } //~MyFreenectDevice(){} // Do not call directly even in child void VideoCallback(void* _rgb, uint32_t timestamp) { Mutex::ScopedLock lock(m_rgb_mutex); uint8_t* rgb = static_cast(_rgb); std::copy(rgb, rgb+getVideoBufferSize(), m_buffer_video.begin()); m_new_rgb_frame = true; }; // Do not call directly even in child void DepthCallback(void* _depth, uint32_t timestamp) { Mutex::ScopedLock lock(m_depth_mutex); uint16_t* depth = static_cast(_depth); for( unsigned int i = 0 ; i < 640*480 ; i++) { int pval = m_gamma[depth[i]]; int lb = pval & 0xff; switch (pval>>8) { case 0: m_buffer_depth[3*i+0] = 255; m_buffer_depth[3*i+1] = 255-lb; m_buffer_depth[3*i+2] = 255-lb; break; case 1: m_buffer_depth[3*i+0] = 255; m_buffer_depth[3*i+1] = lb; m_buffer_depth[3*i+2] = 0; break; case 2: m_buffer_depth[3*i+0] = 255-lb; m_buffer_depth[3*i+1] = 255; m_buffer_depth[3*i+2] = 0; break; case 3: m_buffer_depth[3*i+0] = 0; m_buffer_depth[3*i+1] = 255; m_buffer_depth[3*i+2] = lb; break; case 4: m_buffer_depth[3*i+0] = 0; m_buffer_depth[3*i+1] = 255-lb; m_buffer_depth[3*i+2] = 255; break; case 5: m_buffer_depth[3*i+0] = 0; m_buffer_depth[3*i+1] = 0; m_buffer_depth[3*i+2] = 255-lb; break; default: m_buffer_depth[3*i+0] = 0; m_buffer_depth[3*i+1] = 0; m_buffer_depth[3*i+2] = 0; break; } } m_new_depth_frame = true; } bool getRGB(std::vector &buffer) { Mutex::ScopedLock lock(m_rgb_mutex); if (!m_new_rgb_frame) return false; buffer.swap(m_buffer_video); m_new_rgb_frame = false; return true; } bool getDepth(std::vector &buffer) { Mutex::ScopedLock lock(m_depth_mutex); if (!m_new_depth_frame) return false; buffer.swap(m_buffer_depth); m_new_depth_frame = false; return true; } private: std::vector m_buffer_depth; std::vector m_buffer_video; std::vector m_gamma; Mutex m_rgb_mutex; Mutex m_depth_mutex; bool m_new_rgb_frame; bool m_new_depth_frame; }; Freenect::Freenect freenect; MyFreenectDevice* device; freenect_video_format requested_format(FREENECT_VIDEO_RGB); GLuint gl_depth_tex; GLuint gl_rgb_tex; double freenect_angle(0); int got_frames(0),window(0); int g_argc; char **g_argv; void DrawGLScene() { static std::vector depth(640*480*4); static std::vector rgb(640*480*4); // using getTiltDegs() in a closed loop is unstable /*if(device->getState().m_code == TILT_STATUS_STOPPED){ freenect_angle = device->getState().getTiltDegs(); }*/ device->updateState(); printf("\r demanded tilt angle: %+4.2f device tilt angle: %+4.2f", freenect_angle, device->getState().getTiltDegs()); fflush(stdout); device->getDepth(depth); device->getRGB(rgb); got_frames = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, &depth[0]); glBegin(GL_TRIANGLE_FAN); glColor4f(255.0f, 255.0f, 255.0f, 255.0f); glTexCoord2f(0, 0); glVertex3f(0,0,0); glTexCoord2f(1, 0); glVertex3f(640,0,0); glTexCoord2f(1, 1); glVertex3f(640,480,0); glTexCoord2f(0, 1); glVertex3f(0,480,0); glEnd(); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); if (device->getVideoFormat() == FREENECT_VIDEO_RGB || device->getVideoFormat() == FREENECT_VIDEO_YUV_RGB) glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, &rgb[0]); else glTexImage2D(GL_TEXTURE_2D, 0, 1, 640, 480, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &rgb[0]); glBegin(GL_TRIANGLE_FAN); glColor4f(255.0f, 255.0f, 255.0f, 255.0f); glTexCoord2f(0, 0); glVertex3f(640,0,0); glTexCoord2f(1, 0); glVertex3f(1280,0,0); glTexCoord2f(1, 1); glVertex3f(1280,480,0); glTexCoord2f(0, 1); glVertex3f(640,480,0); glEnd(); glutSwapBuffers(); } void keyPressed(unsigned char key, int x, int y) { if (key == 27) { glutDestroyWindow(window); } if (key == '1') { device->setLed(LED_GREEN); } if (key == '2') { device->setLed(LED_RED); } if (key == '3') { device->setLed(LED_YELLOW); } if (key == '4') { device->setLed(LED_BLINK_GREEN); } if (key == '5') { // 5 is the same as 4 device->setLed(LED_BLINK_GREEN); } if (key == '6') { device->setLed(LED_BLINK_RED_YELLOW); } if (key == '0') { device->setLed(LED_OFF); } if (key == 'f') { if (requested_format == FREENECT_VIDEO_IR_8BIT) requested_format = FREENECT_VIDEO_RGB; else if (requested_format == FREENECT_VIDEO_RGB) requested_format = FREENECT_VIDEO_YUV_RGB; else requested_format = FREENECT_VIDEO_IR_8BIT; device->setVideoFormat(requested_format); } if (key == 'w') { freenect_angle++; if (freenect_angle > 30) { freenect_angle = 30; } } if (key == 's' || key == 'd') { freenect_angle = 0; } if (key == 'x') { freenect_angle--; if (freenect_angle < -30) { freenect_angle = -30; } } if (key == 'e') { freenect_angle = 10; } if (key == 'c') { freenect_angle = -10; } device->setTiltDegrees(freenect_angle); } void ReSizeGLScene(int Width, int Height) { glViewport(0,0,Width,Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (0, 1280, 480, 0, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); } void InitGL(int Width, int Height) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0); glDepthFunc(GL_LESS); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_SMOOTH); glGenTextures(1, &gl_depth_tex); glBindTexture(GL_TEXTURE_2D, gl_depth_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glGenTextures(1, &gl_rgb_tex); glBindTexture(GL_TEXTURE_2D, gl_rgb_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ReSizeGLScene(Width, Height); } void *gl_threadfunc(void *arg) { printf("GL thread\n"); glutInit(&g_argc, g_argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); glutInitWindowSize(1280, 480); glutInitWindowPosition(0, 0); window = glutCreateWindow("LibFreenect"); glutDisplayFunc(&DrawGLScene); glutIdleFunc(&DrawGLScene); glutReshapeFunc(&ReSizeGLScene); glutKeyboardFunc(&keyPressed); InitGL(1280, 480); glutMainLoop(); return NULL; } int main(int argc, char **argv) { device = &freenect.createDevice(0); device->startVideo(); device->startDepth(); gl_threadfunc(NULL); device->stopVideo(); device->stopDepth(); return 0; } libfreenect-0.5.3/wrappers/cpp/libfreenect.hpp000066400000000000000000000222441264163024100214240ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ #pragma once #include "libfreenect.h" #include #include #include #include #include namespace Freenect { class Noncopyable { public: Noncopyable() {} ~Noncopyable() {} private: Noncopyable( const Noncopyable& ); const Noncopyable& operator=( const Noncopyable& ); }; class FreenectTiltState { friend class FreenectDevice; FreenectTiltState(freenect_raw_tilt_state *_state): m_code(_state->tilt_status), m_state(_state) {} public: void getAccelerometers(double* x, double* y, double* z) { freenect_get_mks_accel(m_state, x, y, z); } double getTiltDegs() { return freenect_get_tilt_degs(m_state); } public: freenect_tilt_status_code m_code; private: freenect_raw_tilt_state *m_state; }; class FreenectDevice : Noncopyable { public: FreenectDevice(freenect_context *_ctx, int _index) : m_video_resolution(FREENECT_RESOLUTION_MEDIUM), m_depth_resolution(FREENECT_RESOLUTION_MEDIUM) { if(freenect_open_device(_ctx, &m_dev, _index) < 0) throw std::runtime_error("Cannot open Kinect"); freenect_set_user(m_dev, this); setVideoFormat(FREENECT_VIDEO_RGB, FREENECT_RESOLUTION_MEDIUM); setDepthFormat(FREENECT_DEPTH_11BIT, FREENECT_RESOLUTION_MEDIUM); freenect_set_depth_callback(m_dev, freenect_depth_callback); freenect_set_video_callback(m_dev, freenect_video_callback); } virtual ~FreenectDevice() { if(freenect_close_device(m_dev) < 0){} //FN_WARNING("Device did not shutdown in a clean fashion"); } void startVideo() { if(freenect_start_video(m_dev) < 0) throw std::runtime_error("Cannot start RGB callback"); } void stopVideo() { if(freenect_stop_video(m_dev) < 0) throw std::runtime_error("Cannot stop RGB callback"); } void startDepth() { if(freenect_start_depth(m_dev) < 0) throw std::runtime_error("Cannot start depth callback"); } void stopDepth() { if(freenect_stop_depth(m_dev) < 0) throw std::runtime_error("Cannot stop depth callback"); } void setTiltDegrees(double _angle) { if(freenect_set_tilt_degs(m_dev, _angle) < 0) throw std::runtime_error("Cannot set angle in degrees"); } void setLed(freenect_led_options _option) { if(freenect_set_led(m_dev, _option) < 0) throw std::runtime_error("Cannot set led"); } void updateState() { if (freenect_update_tilt_state(m_dev) < 0) throw std::runtime_error("Cannot update device state"); } FreenectTiltState getState() const { return FreenectTiltState(freenect_get_tilt_state(m_dev)); } void setVideoFormat(freenect_video_format requested_format, freenect_resolution requested_resolution = FREENECT_RESOLUTION_MEDIUM) { if (requested_format != m_video_format || requested_resolution != m_video_resolution) { bool wasRunning = (freenect_stop_video(m_dev) >= 0); freenect_frame_mode mode = freenect_find_video_mode(requested_resolution, requested_format); if (!mode.is_valid) throw std::runtime_error("Cannot set video format: invalid mode"); if (freenect_set_video_mode(m_dev, mode) < 0) throw std::runtime_error("Cannot set video format"); if (wasRunning) freenect_start_video(m_dev); m_video_format = requested_format; m_video_resolution = requested_resolution; } } freenect_video_format getVideoFormat() { return m_video_format; } freenect_resolution getVideoResolution() { return m_video_resolution; } void setDepthFormat(freenect_depth_format requested_format, freenect_resolution requested_resolution = FREENECT_RESOLUTION_MEDIUM) { if (requested_format != m_depth_format || requested_resolution != m_depth_resolution) { bool wasRunning = (freenect_stop_depth(m_dev) >= 0); freenect_frame_mode mode = freenect_find_depth_mode(requested_resolution, requested_format); if (!mode.is_valid) throw std::runtime_error("Cannot set depth format: invalid mode"); if (freenect_set_depth_mode(m_dev, mode) < 0) throw std::runtime_error("Cannot set depth format"); if (wasRunning) freenect_start_depth(m_dev); m_depth_format = requested_format; m_depth_resolution = requested_resolution; } } freenect_depth_format getDepthFormat() { return m_depth_format; } freenect_resolution getDepthResolution() { return m_depth_resolution; } int setFlag(freenect_flag flag, bool value) { return freenect_set_flag(m_dev, flag, value ? FREENECT_ON : FREENECT_OFF); } const freenect_device *getDevice() { return m_dev; } // Do not call directly even in child virtual void VideoCallback(void *video, uint32_t timestamp) { } // Do not call directly even in child virtual void DepthCallback(void *depth, uint32_t timestamp) { } protected: int getVideoBufferSize(){ switch(m_video_format) { case FREENECT_VIDEO_RGB: case FREENECT_VIDEO_BAYER: case FREENECT_VIDEO_IR_8BIT: case FREENECT_VIDEO_IR_10BIT: case FREENECT_VIDEO_IR_10BIT_PACKED: case FREENECT_VIDEO_YUV_RGB: case FREENECT_VIDEO_YUV_RAW: return freenect_find_video_mode(m_video_resolution, m_video_format).bytes; default: return 0; } } int getDepthBufferSize(){ return freenect_get_current_depth_mode(m_dev).bytes; } private: freenect_device *m_dev; freenect_video_format m_video_format; freenect_depth_format m_depth_format; freenect_resolution m_video_resolution; freenect_resolution m_depth_resolution; static void freenect_depth_callback(freenect_device *dev, void *depth, uint32_t timestamp) { FreenectDevice* device = static_cast(freenect_get_user(dev)); device->DepthCallback(depth, timestamp); } static void freenect_video_callback(freenect_device *dev, void *video, uint32_t timestamp) { FreenectDevice* device = static_cast(freenect_get_user(dev)); device->VideoCallback(video, timestamp); } }; class Freenect : Noncopyable { private: typedef std::map DeviceMap; public: Freenect() : m_stop(false) { if(freenect_init(&m_ctx, NULL) < 0) throw std::runtime_error("Cannot initialize freenect library"); // We claim both the motor and camera devices, since this class exposes both. // It does not support audio, so we do not claim it. freenect_select_subdevices(m_ctx, static_cast(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); if(pthread_create(&m_thread, NULL, pthread_callback, (void*)this) != 0) throw std::runtime_error("Cannot initialize freenect thread"); } ~Freenect() { m_stop = true; for(DeviceMap::iterator it = m_devices.begin() ; it != m_devices.end() ; ++it) { delete it->second; } pthread_join(m_thread, NULL); if(freenect_shutdown(m_ctx) < 0){} //FN_WARNING("Freenect did not shutdown in a clean fashion"); } template ConcreteDevice& createDevice(int _index) { DeviceMap::iterator it = m_devices.find(_index); if (it != m_devices.end()) delete it->second; ConcreteDevice * device = new ConcreteDevice(m_ctx, _index); m_devices[_index] = device; return *device; } void deleteDevice(int _index) { DeviceMap::iterator it = m_devices.find(_index); if (it == m_devices.end()) return; delete it->second; m_devices.erase(it); } int deviceCount() { return freenect_num_devices(m_ctx); } // Do not call directly, thread runs here void operator()() { while (!m_stop) { static timeval timeout = { 1, 0 }; int res = freenect_process_events_timeout(m_ctx, &timeout); if (res < 0) { // libusb signals an error has occurred if (res == LIBUSB_ERROR_INTERRUPTED) { // This happens sometimes, it means that a system call in libusb was interrupted somehow (perhaps due to a signal) // The simple solution seems to be just ignore it. continue; } std::stringstream ss; ss << "Cannot process freenect events (libusb error code: " << res << ")"; throw std::runtime_error(ss.str()); } } } static void *pthread_callback(void *user_data) { Freenect* freenect = static_cast(user_data); (*freenect)(); return NULL; } protected: freenect_context *m_ctx; private: volatile bool m_stop; pthread_t m_thread; DeviceMap m_devices; }; } libfreenect-0.5.3/wrappers/csharp/000077500000000000000000000000001264163024100171235ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/README000066400000000000000000000004101264163024100177760ustar00rootroot00000000000000 Just a quick readme for now... will flesh out at some point. Need monodevelop (or the mono compiler) for now. Will provide VS stuff later on. -Compiled stuff from goes to bin folder under the folder this file is in. -Copy over libfreenect.so into bin. -Run! libfreenect-0.5.3/wrappers/csharp/src/000077500000000000000000000000001264163024100177125ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/lib/000077500000000000000000000000001264163024100204605ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/lib/Accelerometer.cs000066400000000000000000000102031264163024100235550ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; namespace freenect { /// /// Provides data from the accelerometer on the Kinect device /// /// /// public class Accelerometer { /// /// Parent Kinect instance /// private Kinect parentDevice; /// /// Number of accelerometer counts per G /// private const double countsPerGravity = 819.0; /// /// Gravity constant /// public const double Gravity = 9.80665; /// /// Gets the X axis value on the accelerometer /// public double X { get { return this.MKS.X; } } // /// Gets the Y axis value on the accelerometer /// public double Y { get { return this.MKS.Y; } } // /// Gets the Z axis value on the accelerometer /// public double Z { get { return this.MKS.Z; } } /// /// Returns raw accelerometer values. There are 819 values per G. Therefore /// the range for this should be [410, 3686] /// public RawValues Raw { get { return this.GetRawAccelerometerValues(); } } /// /// Gets MKS accelerometer values. These are values in m/(s*s). /// public Values MKS { get { return this.GetMKSAccelerometerValues(); } } /// /// Constructor /// /// /// Parent device that this accelerometer is part of /// internal Accelerometer(Kinect parent) { this.parentDevice = parent; } /// /// Gets MKS accelerometer values. Support function for the KinectAccelerometer.MKS property. /// /// /// with X, Y, Z populated with MKS accel readings. /// private Values GetMKSAccelerometerValues() { Values values = new Values(); // Calculate MKS values.X = (double)this.Raw.X / countsPerGravity * Gravity; values.Y = (double)this.Raw.Y / countsPerGravity * Gravity; values.Z = (double)this.Raw.Z / countsPerGravity * Gravity; return values; } /// /// Gets raw accelerometer values. Support function for KinectAccelerometer.Raw property. /// /// /// with X, Y, Z populated with Raw accel readings. /// private RawValues GetRawAccelerometerValues() { RawValues values = new RawValues(); values.X = this.parentDevice.cachedDeviceState.AccelerometerX; values.Y = this.parentDevice.cachedDeviceState.AccelerometerY; values.Z = this.parentDevice.cachedDeviceState.AccelerometerZ; return values; } /// /// Set of raw accelerometer count values /// public struct RawValues { public Int16 X; public Int16 Y; public Int16 Z; } /// /// Set of MKS accelerometer values. /// public struct Values { public double X; public double Y; public double Z; } } } libfreenect-0.5.3/wrappers/csharp/src/lib/AssemblyInfo.cs000066400000000000000000000017341264163024100234070ustar00rootroot00000000000000using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("freenectdotnet")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("freenect")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] libfreenect-0.5.3/wrappers/csharp/src/lib/BaseCamera.cs000066400000000000000000000110731264163024100227740ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Collections.Generic; using System.ComponentModel; namespace freenect { /// /// Base camera class. Provides access to Kinect cameras. /// public abstract class BaseCamera { /// /// Parent Kinect instance /// protected Kinect parentDevice; /// /// Current capture mode /// protected FrameMode captureMode; /// /// Direct access data buffer for the camera /// protected IntPtr dataBuffer = IntPtr.Zero; /// /// Data map waiting for data /// protected BaseDataMap nextFrameData = null; /// /// Callback (delegate) for camera data /// protected FreenectCameraDataCallback DataCallback; /// /// Event raised when data (an image) has been received. /// public event DataReceivedEventHandler DataReceived = delegate { }; /// /// Gets whether this camera is streaming data /// public bool IsRunning { get; protected set; } /// /// Gets or sets the direct data buffer the USB stream will use for /// the video camera. This should be a pinned location in memory. /// If set to IntPtr.Zero, the library will manage the data buffer /// for you. /// public IntPtr DataBuffer { get { return this.dataBuffer; } set { this.SetDataBuffer(value); } } /// /// Base camera constructor /// /// /// A /// internal BaseCamera(Kinect parent) { // Save parent device this.parentDevice = parent; // Not running by default this.IsRunning = false; // Create callback this.DataCallback = new FreenectCameraDataCallback(this.HandleDataReceived); } /// /// Handles image data from teh video camera /// /// /// A /// /// /// A /// /// /// A /// protected void HandleDataReceived(IntPtr device, IntPtr imageData, UInt32 timestamp) { // Calculate datetime from timestamp DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(timestamp); // Send out event this.DataReceived(this, new DataReceivedEventArgs(dateTime, this.nextFrameData)); } /// /// Sets the direct access buffer for the Camera. /// /// /// Pointer to the direct access data buffer for the Camera. /// protected abstract void SetDataBuffer(IntPtr ptr); /// /// Delegate for camera data events /// public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e); /// /// Event data for camera data received events /// public class DataReceivedEventArgs { /// /// Gets the timestamp for this data /// public DateTime Timestamp { get; private set; } /// /// Gets... the data /// public BaseDataMap Data { get; private set; } public DataReceivedEventArgs(DateTime timestamp, BaseDataMap b) { this.Timestamp = timestamp; this.Data = b; } } } }libfreenect-0.5.3/wrappers/csharp/src/lib/BaseDataMap.cs000066400000000000000000000063161264163024100231170ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Runtime.InteropServices; namespace freenect { /// /// Represents a generic map of data values /// public class BaseDataMap { /// /// GC handle to the data in the map /// private GCHandle dataHandle; /// /// Gets the width of the map /// public int Width { get; private set; } /// /// Gets the height of the map /// public int Height { get; private set; } /// /// Gets the raw data in the DataMap. This data is in a 1-dimensional /// array so it's easy to work with in unsafe code. /// public byte[] Data { get; private set; } /// /// Gets the data pointer from the Kinect library /// public IntPtr DataPointer { get; private set; } /// /// Gets the mode in which this data was captured. /// public FrameMode CaptureMode { get; private set; } /// /// Constructor with only mode speicifed. Data is allocated inside. /// /// /// A /// internal BaseDataMap(FrameMode mode) { // Save format and resolution this.Width = mode.Width; this.Height = mode.Height; this.CaptureMode = mode; this.Data = new byte[mode.Size]; this.dataHandle = GCHandle.Alloc(this.Data, GCHandleType.Pinned); this.DataPointer = this.dataHandle.AddrOfPinnedObject(); } /// /// Constructor with only mode and data pointer specified. No allocation is made. /// /// /// A /// internal BaseDataMap(FrameMode mode, IntPtr bufferPointer) { this.Width = mode.Width; this.Height = mode.Height; this.CaptureMode = mode; this.Data = null; this.dataHandle = default(GCHandle); this.DataPointer = bufferPointer; } /// /// Destructoooorrr /// ~BaseDataMap() { if(this.dataHandle != default(GCHandle)) { this.dataHandle.Free(); } } } } libfreenect-0.5.3/wrappers/csharp/src/lib/DepthCamera.cs000066400000000000000000000136121264163024100231670ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Drawing; namespace freenect { /// /// Provides access to the depth camera on the Kinect /// public class DepthCamera : BaseCamera { /// /// Gets or sets the depth camera's mode. /// public DepthFrameMode Mode { get { return (DepthFrameMode)this.captureMode; } set { this.SetDepthMode(value); } } /// /// List of available, valid modes for the depth camera /// public DepthFrameMode[] Modes { get; private set; } /// /// Constructor /// /// /// Parent device that this depth camera is part of /// internal DepthCamera(Kinect parent) : base(parent) { // Update lsit of available modes for this camera this.UpdateDepthModes(); // Set the mode to the first available mode this.Mode = this.Modes[0]; // Setup callbacks KinectNative.freenect_set_depth_callback(parent.devicePointer, this.DataCallback); } /// /// Starts streaming depth data from this camera /// public void Start() { // Update depth map before starting this.UpdateNextFrameDepthMap(); // Start int result = KinectNative.freenect_start_depth(this.parentDevice.devicePointer); if(result != 0) { throw new Exception("Could not start depth stream. Error Code: " + result); } // All done this.IsRunning = true; } /// /// Stops streaming depth data from this camera /// public void Stop() { if(this.IsRunning == false) { // Not running, nothing to do return; } // Stop camera int result = KinectNative.freenect_stop_depth(this.parentDevice.devicePointer); if(result != 0) { throw new Exception("Could not stop depth stream. Error Code: " + result); } this.IsRunning = false; } /// /// Sets the direct access buffer for the DepthCamera. /// /// /// Pointer to the direct access data buffer for the DepthCamera. /// protected override void SetDataBuffer(IntPtr ptr) { // Save data buffer this.dataBuffer = ptr; // Tell the kinect library about it KinectNative.freenect_set_depth_buffer(this.parentDevice.devicePointer, ptr); // update depth map this.UpdateNextFrameDepthMap(); } /// /// Sets the current depth camera mode /// /// /// Depth camera mode to switch to. /// protected void SetDepthMode(DepthFrameMode mode) { // Is this a different mode? if(this.Mode == mode) { return; } // Stop camera first if running bool running = this.IsRunning; if(running) { this.Stop(); } // Check to make sure mode is valid by finding it again DepthFrameMode foundMode = DepthFrameMode.Find(mode.Format, mode.Resolution); if(foundMode == null) { throw new Exception("Invalid Depth Camera Mode: [" + mode.Format + ", " + mode.Resolution + "]"); } // Save mode this.captureMode = mode; // All good, switch to new mode int result = KinectNative.freenect_set_depth_mode(this.parentDevice.devicePointer, foundMode.nativeMode); if(result != 0) { throw new Exception("Mode switch failed. Error Code: " + result); } // Update depth map this.UpdateNextFrameDepthMap(); // If we were running before, start up again if(running) { this.Start(); } } /// /// Updates list of depth modes that this camera has. /// private void UpdateDepthModes() { List modes = new List(); // Get number of modes int numModes = KinectNative.freenect_get_depth_mode_count(this.parentDevice.devicePointer); // Go through modes for(int i = 0; i < numModes; i++) { DepthFrameMode mode = (DepthFrameMode)FrameMode.FromInterop(KinectNative.freenect_get_depth_mode(i), FrameMode.FrameModeType.DepthFormat); if(mode != null) { modes.Add(mode); } } // All done this.Modes = modes.ToArray(); } /// /// Updates the next frame depth map that's waiting for data with any state changes /// protected void UpdateNextFrameDepthMap() { if(this.DataBuffer == IntPtr.Zero) { // have to set our own buffer as the depth buffer this.nextFrameData = new DepthMap(this.Mode); } else { // already have a buffer from user this.nextFrameData = new DepthMap(this.Mode, this.DataBuffer); } // Set new buffer at library level; KinectNative.freenect_set_depth_buffer(this.parentDevice.devicePointer, this.nextFrameData.DataPointer); } } } libfreenect-0.5.3/wrappers/csharp/src/lib/DepthFrameMode.cs000066400000000000000000000042461264163024100236410ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Collections.Generic; namespace freenect { /// /// Depth frame mode. /// public class DepthFrameMode : FrameMode { /// /// Gets the format for this depth frame mode /// public DepthFormat Format { get { return this.depthFormat; } } /// /// Ninja constructor /// internal DepthFrameMode() { } /// /// Finds a mode, given a format and resolution. /// /// /// Depth format for the mode /// /// /// Resolution for the mode /// /// /// Mode with the format/resolution combo. Null if the combination is invalid. /// public static DepthFrameMode Find(DepthFormat format, Resolution resolution) { return (DepthFrameMode)FrameMode.FromInterop(KinectNative.freenect_find_depth_mode(resolution, format), FrameMode.FrameModeType.DepthFormat); } } }libfreenect-0.5.3/wrappers/csharp/src/lib/DepthMap.cs000066400000000000000000000033651264163024100225200ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Runtime.InteropServices; namespace freenect { /// /// Represents a map of depth values from the DepthCamera /// public class DepthMap : BaseDataMap { /// /// Constructor #1 /// /// /// A /// public DepthMap(FrameMode mode) : base(mode) { } /// /// Constructor #2 /// /// /// A /// /// /// A /// public DepthMap(FrameMode mode, IntPtr buffer) : base(mode, buffer) { } } } libfreenect-0.5.3/wrappers/csharp/src/lib/Enumerations.cs000066400000000000000000000051721264163024100234650ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Collections.Generic; namespace freenect { /// /// Data formats for the video camera /// public enum VideoFormat : int { RGB = 0, Bayer = 1, Infrared8Bit = 2, Infrared10Bit = 3, InfraredPacked10Bit = 4, YUVRGB = 5, YUVRaw = 6 } /// /// Data formats for the depth camera /// public enum DepthFormat : int { Depth11Bit = 0, Depth10Bit = 1, DepthPacked11Bit = 2, DepthPacked10Bit = 3, DepthRegistered = 4, DepthMM = 5 } /// /// Resolution settings. /// /// LOW = QVGA (320x240) /// MEDIUM = VGA (640x480 for video, 640x488 for IR) /// HIGH = SXGA (1280x1024) /// public enum Resolution : int { Low = 0, Medium = 1, High = 2 } /// /// LED colors. None means LED is off. /// public enum LEDColor : int { None = 0, Green = 1, Red = 2, Yellow = 3, BlinkYellow = 4, BlinkGreen = 5, BlinkRedYellow = 6 } /// /// Different states the tilt motor can be in operation /// public enum MotorTiltStatus : int { Stopped = 0x00, AtLimit = 0x01, Moving = 0x04 } /// /// Logging levels from the C library /// public enum LoggingLevel : int { Fatal = 0, Error, Warning, Notice, Info, Debug, Spew, Flood, } } libfreenect-0.5.3/wrappers/csharp/src/lib/FrameMode.cs000066400000000000000000000112041264163024100226440ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Collections.Generic; namespace freenect { /// /// Abstract frame mode. Base class for Video and Depth frame modes. Not /// to be used directly. /// public abstract class FrameMode { /// /// Gets the resolution setting for this mode (low, medium, high) /// public Resolution Resolution { get; private set; } /// /// Gets the total size of the frame in bytes /// public int Size { get; private set; } /// /// Gets the width of the frame in pixels /// public int Width { get; private set; } /// /// Gets the height of the frame in pixels /// public int Height { get; private set; } /// /// Gets the number of bits per pixel in the frame /// public int DataBitsPerPixel { get; private set; } /// /// Gets the number of pading bits per pixel in the frame /// public int PaddingBitsPerPixel { get; private set; } /// /// Gets the framerate in Hz that you can expect (sort of) /// public int FrameRate { get; private set; } /// /// Video format for this frame mode. This doesn't have to be valid /// as the frame mode could be for depth. /// protected VideoFormat videoFormat; /// /// Depth format for this frame mode. This doesn't have to be valid /// as the frame mode could be for video. /// protected DepthFormat depthFormat; /// /// Native mode struct that this managed one was spawned from /// internal FreenectFrameMode nativeMode; /// /// Gets a nice C# library version of the Frame Mode class /// /// /// A /// /// /// A /// internal static FrameMode FromInterop(FreenectFrameMode nativeMode, FrameModeType type) { FrameMode mode = null; // Make sure mode is valid if(nativeMode.IsValid == 0) { return null; } // Figure out what type of mode it is if(type == FrameMode.FrameModeType.VideoFormat) { mode = new VideoFrameMode(); } else if(type == FrameMode.FrameModeType.DepthFormat) { mode = new DepthFrameMode(); } // Copy over rest of data mode.nativeMode = nativeMode; mode.Size = nativeMode.Bytes; mode.Width = nativeMode.Width; mode.Height = nativeMode.Height; mode.Resolution = nativeMode.Resolution; mode.DataBitsPerPixel = nativeMode.DataBitsPerPixel; mode.PaddingBitsPerPixel = nativeMode.PaddingBitsPerPixel; mode.FrameRate = nativeMode.Framerate; mode.videoFormat = nativeMode.VideoFormat; mode.depthFormat = nativeMode.DepthFormat; return mode; } /// /// Gets a string representation of the FrameMode /// /// /// A /// public override String ToString() { if(this is VideoFrameMode) { return this.Width + "x" + this.Height + " : " + this.videoFormat.ToString(); } else { return this.Width + "x" + this.Height + " : " + this.depthFormat.ToString(); } } /// /// Format mode type. This is only used interally. Don't touch! /// internal enum FrameModeType { VideoFormat, DepthFormat } } }libfreenect-0.5.3/wrappers/csharp/src/lib/ImageMap.cs000066400000000000000000000034511264163024100224720ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Collections.Generic; using System.Drawing; using System.Runtime.InteropServices; namespace freenect { /// /// Represents a map of rgb values from the RGBCamera /// public class ImageMap : BaseDataMap { /// /// Constructor #1 /// /// /// A /// public ImageMap(FrameMode mode) : base(mode) { } /// /// Constructor #2 /// /// /// A /// /// /// A /// public ImageMap(FrameMode mode, IntPtr buffer) : base(mode, buffer) { } } } libfreenect-0.5.3/wrappers/csharp/src/lib/Kinect.cs000066400000000000000000000202121264163024100222210ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Runtime.InteropServices; using System.Threading; namespace freenect { /// /// Kinect device. This wraps functionality associated with the entire Kinect /// device into a happy little bundle. /// /// /// public class Kinect { /// /// Gets or sets the logging level for the Kinect library. This controls /// how much debugging information is sent to the logging callback /// public static LoggingLevel LogLevel { get { return Kinect.logLevel; } set { Kinect.SetLogLevel(value); } } /// /// Raised when a log item is received from the low level Kinect library. /// public static event LogEventHandler Log = delegate { }; /// /// Gets the device ID for this Kinect device /// public int DeviceID { get; private set; } /// /// Gets whether the connection to the device is open /// public bool IsOpen { get; private set; } /// /// Gets the LED on this Kinect device /// public LED LED { get; private set; } /// /// Gets the Motor instance for this Kinect device /// public Motor Motor { get; private set; } /// /// Gets the accelerometer for this Kinect device /// public Accelerometer Accelerometer { get; private set; } /// /// Gets the RGB camera for this Kinect device /// public VideoCamera VideoCamera { get; private set; } /// /// Gets the depth camera for this Kinect device /// public DepthCamera DepthCamera { get; private set; } /// /// Gets or sets the name for this Kinect Device. /// /// /// This means nothing at all to the actual library, but can be useful for /// debugging/presentation reasons. The default value is "Device {Kinect.DeviceID}" /// without the curly braces. For example, "Device 0" or "Device 1". /// But you can make it whatever the hell you want. /// public string Name { get; set; } /// /// Current logging level for the kinect session (for all devices) /// private static LoggingLevel logLevel; /// /// Pointer to native device object /// internal IntPtr devicePointer = IntPtr.Zero; /// /// Cached device state that can be used after a call to Kinect.UpdateStatus /// This can be used to save some USB or P/Invoke calls. /// internal FreenectTiltState cachedDeviceState; /// /// Constructor /// /// /// ID of the Kinect Device. This is a value in the range [0, Kinect.DeviceCount - 1] /// public Kinect(int id) { // Make sure id is under DeviceCount if(id >= Kinect.DeviceCount) { throw new ArgumentOutOfRangeException("The device ID has to be in the range [0, Kinect.DeviceCount - 1]"); } // Store device ID for later this.DeviceID = id; } /// /// Gets number of Kinect devices connected /// public static int DeviceCount { get { return Kinect.GetDeviceCount(); } } /// /// Opens up the connection to this Kinect device /// public void Open() { int result = KinectNative.freenect_open_device(KinectNative.Context, ref this.devicePointer, this.DeviceID); if(result != 0) { throw new Exception("Could not open connection to Kinect Device (ID=" + this.DeviceID + "). Error Code = " + result); } // Create child instances this.LED = new LED(this); this.Motor = new Motor(this); this.Accelerometer = new Accelerometer(this); this.VideoCamera = new VideoCamera(this); this.DepthCamera = new DepthCamera(this); //Register the device KinectNative.RegisterDevice(this.devicePointer, this); // Open now this.IsOpen = true; } /// /// Closes the connection to this Kinect device /// public void Close() { // Stop Cameras if(this.VideoCamera.IsRunning) { this.VideoCamera.Stop(); } if(this.DepthCamera.IsRunning) { this.DepthCamera.Stop(); } // Close device int result = KinectNative.freenect_close_device(this.devicePointer); if(result != 0) { throw new Exception("Could not close connection to Kinect Device (ID=" + this.DeviceID + "). Error Code = " + result); } // Dispose of child instances this.LED = null; this.Motor = null; this.Accelerometer = null; this.VideoCamera = null; this.DepthCamera = null; // Unegister the device KinectNative.UnregisterDevice(this.devicePointer); // Not open anymore this.IsOpen = false; } /// /// Gets updated device status from the Kinect. This updates any properties in the /// child devices (Motor, LED, etc.) /// public void UpdateStatus() { // Ask for new device status KinectNative.freenect_update_tilt_state(this.devicePointer); // Get updated device status IntPtr ptr = KinectNative.freenect_get_tilt_state(this.devicePointer); this.cachedDeviceState = (FreenectTiltState)Marshal.PtrToStructure(ptr, typeof(FreenectTiltState)); } /// /// Makes the base library handle any pending USB events. Either this, or UpdateStatus /// should be called repeatedly. /// public static void ProcessEvents() { KinectNative.freenect_process_events(KinectNative.Context); } /// /// Shuts down the Kinect.NET library and closes any open devices. /// public static void Shutdown() { KinectNative.ShutdownContext(); } /// /// Gets the number of Kinect devices connected /// /// /// This is just a support function for the Kinect.DeviceCount property /// /// /// Number of Kinect devices connected. /// private static int GetDeviceCount() { // Now we can just return w/e native method puts out return KinectNative.freenect_num_devices(KinectNative.Context); } /// /// Sets the logging level for the Kinect session. Support function for Kinect.LogLevel property. /// /// /// A /// private static void SetLogLevel(LoggingLevel level) { KinectNative.freenect_set_log_level(KinectNative.Context, level); Kinect.logLevel = level; } /// /// Logging callback. /// /// /// A /// /// /// A /// /// /// A /// internal static void LogCallback(IntPtr device, LoggingLevel logLevel, string message) { Kinect realDevice = KinectNative.GetDevice(device); Kinect.Log(null, new LogEventArgs(realDevice, logLevel, message)); } } } libfreenect-0.5.3/wrappers/csharp/src/lib/KinectNative.cs000066400000000000000000000252051264163024100233770ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Threading; using System.Collections.Generic; using System.Runtime.InteropServices; namespace freenect { /// /// Provides access to native libfreenect calls. These are "ugly" calls used internally /// in the wrapper. /// /// /// class KinectNative { /// /// Main freenect context. There is one per session. /// private static IntPtr freenectContext = IntPtr.Zero; /// /// Map between native pointers to actual Kinect devices /// private static Dictionary deviceMap = new Dictionary(); /// /// Callback delegate for log messages coming in from the C library. /// private static FreenectLogCallback LogCallback = new FreenectLogCallback(Kinect.LogCallback); /// /// Gets a freenect context to work with. /// public static IntPtr Context { get { // Make sure we have a context if(KinectNative.freenectContext == IntPtr.Zero) { KinectNative.InitializeContext(); } // Return it return KinectNative.freenectContext; } } /// /// Shuts down the context and closes any open devices. /// public static void ShutdownContext() { // Close all devices foreach(Kinect device in KinectNative.deviceMap.Values) { device.Close(); } // Shutdown context int result = KinectNative.freenect_shutdown(KinectNative.freenectContext); if(result != 0) { throw new Exception("Could not shutdown freenect context. Error Code:" + result); } // Dispose pointer KinectNative.freenectContext = IntPtr.Zero; } /// /// Gets a kinect device given it's native pointer. This is /// useful for callbacks. /// /// /// A /// /// /// A /// public static Kinect GetDevice(IntPtr pointer) { if(KinectNative.deviceMap.ContainsKey(pointer) == false) { return null; } return KinectNative.deviceMap[pointer]; } /// /// Registers a device and its native pointer /// /// /// A /// /// /// A /// public static void RegisterDevice(IntPtr pointer, Kinect device) { if(KinectNative.deviceMap.ContainsKey(pointer)) { KinectNative.deviceMap.Remove(pointer); } KinectNative.deviceMap.Add(pointer, device); } /// /// Unregister the device pointed to by the specified native pointer. /// /// /// A /// public static void UnregisterDevice(IntPtr pointer) { if(KinectNative.deviceMap.ContainsKey(pointer)) { KinectNative.deviceMap.Remove(pointer); } } /// /// Initializes the freenect context /// private static void InitializeContext() { int result = KinectNative.freenect_init(ref KinectNative.freenectContext, IntPtr.Zero); if(result != 0) { throw new Exception("Could not initialize freenect context. Error Code:" + result); } // Set callbacks for logging KinectNative.freenect_set_log_callback(KinectNative.freenectContext, LogCallback); } [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_init(ref IntPtr context, IntPtr freenectUSBContext); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_shutdown(IntPtr context); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern void freenect_set_log_level(IntPtr context, LoggingLevel level); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern void freenect_set_log_callback(IntPtr context, FreenectLogCallback callback); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_process_events(IntPtr context); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_num_devices(IntPtr context); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_open_device(IntPtr context, ref IntPtr device, int index); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_close_device(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern void freenect_set_depth_callback(IntPtr device, FreenectCameraDataCallback callback); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern void freenect_set_video_callback(IntPtr device, FreenectCameraDataCallback callback); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_set_depth_buffer(IntPtr device, IntPtr buf); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_set_video_buffer(IntPtr device, IntPtr buf); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_start_depth(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_start_video(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_stop_depth(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_stop_video(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_update_tilt_state(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern IntPtr freenect_get_tilt_state(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern double freenect_get_tilt_degs(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_set_tilt_degs(IntPtr device, double angle); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern MotorTiltStatus freenect_get_tilt_status(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_set_led(IntPtr device, LEDColor color); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_get_video_mode_count(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern FreenectFrameMode freenect_get_video_mode(int modeNum); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern FreenectFrameMode freenect_get_current_video_mode(); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern FreenectFrameMode freenect_find_video_mode(Resolution resolution, VideoFormat videoFormat); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_set_video_mode(IntPtr device, FreenectFrameMode mode); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_get_depth_mode_count(IntPtr device); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern FreenectFrameMode freenect_get_depth_mode(int modeNum); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern FreenectFrameMode freenect_get_current_depth_mode(); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern FreenectFrameMode freenect_find_depth_mode(Resolution resolution, DepthFormat depthFormat); [DllImport("freenect", CallingConvention=CallingConvention.Cdecl)] public static extern int freenect_set_depth_mode(IntPtr device, FreenectFrameMode mode); } /// /// Frame capture settings for all video/depth feeds /// [StructLayout(LayoutKind.Explicit)] internal struct FreenectFrameMode { [FieldOffset(0)] public UInt32 Reserved; [FieldOffset(4)] public Resolution Resolution; [FieldOffset(8)] public VideoFormat VideoFormat; [FieldOffset(8)] public DepthFormat DepthFormat; [FieldOffset(12)] public int Bytes; [FieldOffset(16)] public short Width; [FieldOffset(18)] public short Height; [FieldOffset(20)] public byte DataBitsPerPixel; [FieldOffset(21)] public byte PaddingBitsPerPixel; [FieldOffset(22)] public byte Framerate; [FieldOffset(23)] public byte IsValid; } /// /// Device tilt state values. This holds stuff like accel and tilt status /// internal struct FreenectTiltState { public Int16 AccelerometerX; public Int16 AccelerometerY; public Int16 AccelerometerZ; public SByte TiltAngle; public MotorTiltStatus TiltStatus; } /// /// "Native" callback for freelect library logging /// [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void FreenectLogCallback(IntPtr device, LoggingLevel logLevel, string message); /// /// "Native" callback for camera data /// [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void FreenectCameraDataCallback(IntPtr device, IntPtr data, UInt32 timestamp); } libfreenect-0.5.3/wrappers/csharp/src/lib/LED.cs000066400000000000000000000044621264163024100214210ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; namespace freenect { /// /// Provides control over the LED on the Kinect /// /// /// public class LED { /// /// Parent Kinect instance /// private Kinect parentDevice; /// /// Current color set on the LED /// private LEDColor color; /// /// Gets or sets the LED color on the Kinect device /// /// Gets or sets 'color' field public LEDColor Color { get { return this.color; } set { this.SetLEDColor(value); } } /// /// Constructor /// /// /// Parent device that this LED is part of /// internal LED(Kinect parent) { this.parentDevice = parent; } /// /// Sets the color for the LED on the Kinect. /// /// /// Color value /// private void SetLEDColor(LEDColor color) { int result = KinectNative.freenect_set_led(this.parentDevice.devicePointer, color); if(result != 0) { throw new Exception("Could not set color to " + color + ". Error Code:" + result); } this.color = color; } } } libfreenect-0.5.3/wrappers/csharp/src/lib/LogEventArgs.cs000066400000000000000000000042661264163024100233570ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; namespace freenect { /// /// Delegate for Kinect.Log event /// public delegate void LogEventHandler(object sender, LogEventArgs e); /// /// Log event data /// /// /// public class LogEventArgs { /// /// Gets the Kinect device this log item originated from /// public Kinect Device { get; set; } /// /// Gets the timestamp for this log item. This is done on the C# /// side and does not mean it was SENT EXACTLY at the specified /// time from the Kinect low level library. /// public DateTime Timestamp { get; private set; } /// /// Gets the logging level the library it set to /// public LoggingLevel LogLevel { get; private set; } /// /// Gets the log item text /// public string Message { get; private set; } public LogEventArgs(Kinect device, LoggingLevel logLevel, string message) { this.Device = device; this.LogLevel = logLevel; this.Message = message; } } } libfreenect-0.5.3/wrappers/csharp/src/lib/Motor.cs000066400000000000000000000101051264163024100221040ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; namespace freenect { /// /// Provides control over the Motor on the Kinect /// /// /// public class Motor { /// /// Parent Kinect instance /// private Kinect parentDevice; /// /// Current /// private double commandedTilt; /// /// Gets the commanded tilt value [-1.0, 1.0] for the motor. This is just the tilt /// value that the motor was last asked to go to through Motor.Tilt. This doesn't /// correspond to the actual angle at the physical motor. For that value, see Motor.Tilt. /// public double CommandedTilt { get { return this.commandedTilt; } } /// /// Gets the actual raw tilt value of the motor on the kinect [-128, 128] /// public int RawTilt { get { return (int)this.parentDevice.cachedDeviceState.TiltAngle; } } /// /// Gets or sets the tilt angle of the motor on the Kinect device. /// Accepted values are [-1.0, 1.0]. When queried, this returns the current /// tilt value/status of the motor as it's moving into position. /// To get the commanded tilt value after setting this value, you can /// use the Motor.CommandedTilt property. /// public double Tilt { get { return this.GetMotorTilt(); } set { this.SetMotorTilt(value); } } /// /// Gets the status of the tilt motor. /// public MotorTiltStatus TiltStatus { get { return this.parentDevice.cachedDeviceState.TiltStatus; } } /// /// Constructor /// /// /// Parent device that this Motor is part of /// internal Motor(Kinect parent) { this.parentDevice = parent; // Set tilt to 0 to start this.Tilt = 0; } /// /// Gets the motor's actual tilt angle /// /// /// Actual tilt angle of the motor as it's moving /// private double GetMotorTilt() { double rawAngle = this.parentDevice.cachedDeviceState.TiltAngle; if(rawAngle == -128) { return -2.0f; } return Math.Round(rawAngle / 61.0, 2); } /// /// Sets the motor's tilt angle. /// /// /// Value between [-1.0, 1.0] /// private void SetMotorTilt(double angle) { // Check if value is in valid ranges if(angle < -1.0 || angle > 1.0) { throw new ArgumentOutOfRangeException("Motor tilt has to be in the range [-1.0, 1.0]"); } // Figure out raw angle between -31 and 31 double rawAngle = Math.Round(angle * 31); // Call native func. int result = KinectNative.freenect_set_tilt_degs(this.parentDevice.devicePointer, rawAngle); if(result != 0) { throw new Exception("Coult not set raw motor tilt angle to " + angle + ". Error Code: " + result); } // Save commanded tilt this.commandedTilt = angle; } } } libfreenect-0.5.3/wrappers/csharp/src/lib/SwapBufferCollection.cs000066400000000000000000000106261264163024100250740ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Runtime.InteropServices; namespace freenect { /// /// Represents an collection of swap buffers. Data in the buffer is /// safe to pass to unmanaged calls as it is free. This however means that /// to prevent memory leaks, you MUST call the Dispose method after you are done /// with the collection. /// /// /// public class SwapBufferCollection : IDisposable { /// /// GC handles for each of the buffers in this collection /// private GCHandle[] bufferHandles; /// /// Gets the buffer at the specified index /// /// /// Index of buffer to get to. Range is [0, Count - 1] /// public T[] this[int index] { get { return (T[])this.bufferHandles[index].Target; } } /// /// Gets the size of the collection /// public int Count { get; private set; } /// /// Gets the size of each buffer in the collection /// public int BufferSize { get; private set; } /// /// Create a swap buffer collection of numBuffers size with buffers of size /// bufferSize /// /// /// Number of buffers to create in the collection /// /// /// Size of each swap buffer /// public SwapBufferCollection(int numBuffers, int bufferSize) { // Save some state this.BufferSize = bufferSize; this.Count = numBuffers; // Allocate buffers and save pinned handles to them this.bufferHandles = new GCHandle[numBuffers]; for(int i = 0; i < numBuffers; i++) { var buffer = new T[bufferSize]; this.bufferHandles[i] = GCHandle.Alloc(buffer, GCHandleType.Pinned); } } /// /// Gets the handle to the buffer at the specified index. This is useful for passing /// to unmanaged code. /// /// /// Index of the buffer to get pointer to. Range = [0, Count - 1]. /// /// /// Pointer to buffer of data /// public IntPtr GetHandle(int index) { return this.bufferHandles[index].AddrOfPinnedObject(); } /// /// Swaps the buffers at the specified indices. After this point accessing /// index1 will get you data which was previously at index2 and vice /// versa. WARNING: This operation is NOT thread safe. /// /// /// First index in the swap. Range = [0, Count - 1]. /// /// /// Second index in the swap. Range = [0, Count - 1]. /// public void Swap(int index1, int index2) { if(index1 > this.Count - 1 || index2 > this.Count - 1) { throw new ArgumentOutOfRangeException("Indices for swapping have to be between 0 and Count - 1"); } if(index1 == index2) { // Nothing to do return; } // Swap var tmp = this.bufferHandles[index1]; this.bufferHandles[index1] = this.bufferHandles[index2]; this.bufferHandles[index2] = tmp; } /// /// Disposes the buffer collection and any unmanaged resources. /// public void Dispose() { // Free all GC handles for(int i = 0; i < this.Count; i++) { this.bufferHandles[i].Free(); } } } }libfreenect-0.5.3/wrappers/csharp/src/lib/VS2008/000077500000000000000000000000001264163024100213225ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/lib/VS2008/freenectdotnet.csproj000066400000000000000000000064031264163024100255600ustar00rootroot00000000000000 Debug AnyCPU 9.0.21022 2.0 {360413F9-4D9B-46BE-BEC7-9B666850ED8C} Library freenect freenectdotnet v3.5 true full false ..\..\..\bin\ DEBUG prompt 4 false true none false ..\..\..\bin\ prompt 4 false true AssemblyInfo.cs Kinect.cs KinectNative.cs Motor.cs LED.cs DepthCamera.cs Accelerometer.cs LogEventArgs.cs DepthMap.cs ImageMap.cs VideoCamera.cs SwapBufferCollection.cs Enumerations.cs FrameMode.cs DepthFrameMode.cs VideoFrameMode.cs BaseCamera.cs BaseDataMap.cs libfreenect-0.5.3/wrappers/csharp/src/lib/VS2008/freenectdotnet.sln000066400000000000000000000016431264163024100250550ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "freenectdotnet", "freenectdotnet.csproj", "{360413F9-4D9B-46BE-BEC7-9B666850ED8C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Debug|Any CPU.Build.0 = Debug|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Release|Any CPU.ActiveCfg = Release|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = freenectdotnet.csproj EndGlobalSection EndGlobal libfreenect-0.5.3/wrappers/csharp/src/lib/VS2010/000077500000000000000000000000001264163024100213135ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/lib/VS2010/freenectdotnet.csproj000066400000000000000000000141251264163024100255510ustar00rootroot00000000000000 Debug AnyCPU 9.0.21022 2.0 {360413F9-4D9B-46BE-BEC7-9B666850ED8C} Library freenect freenectdotnet v3.5 3.5 publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true true full false ..\..\..\bin\ DEBUG prompt 4 false true AllRules.ruleset none false ..\..\..\bin\ prompt 4 false true AllRules.ruleset true ..\..\..\bin\ DEBUG true full x64 prompt AllRules.ruleset false false ..\..\..\bin\ true x64 prompt AllRules.ruleset false false Accelerometer.cs AssemblyInfo.cs DepthCamera.cs Kinect.cs KinectNative.cs Motor.cs LED.cs LogEventArgs.cs DepthMap.cs ImageMap.cs VideoCamera.cs SwapBufferCollection.cs BaseCamera.cs BaseDataMap.cs DepthFrameMode.cs Enumerations.cs FrameMode.cs VideoFrameMode.cs False .NET Framework 3.5 SP1 Client Profile false False .NET Framework 3.5 SP1 true False Windows Installer 3.1 true libfreenect-0.5.3/wrappers/csharp/src/lib/VS2010/freenectdotnet.sln000066400000000000000000000025521264163024100250460ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C# Express 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "freenectdotnet", "freenectdotnet.csproj", "{360413F9-4D9B-46BE-BEC7-9B666850ED8C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Debug|Any CPU.Build.0 = Debug|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Debug|x64.ActiveCfg = Debug|x64 {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Debug|x64.Build.0 = Debug|x64 {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Release|Any CPU.ActiveCfg = Release|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Release|Any CPU.Build.0 = Release|Any CPU {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Release|x64.ActiveCfg = Release|x64 {360413F9-4D9B-46BE-BEC7-9B666850ED8C}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = freenectdotnet.csproj EndGlobalSection EndGlobal libfreenect-0.5.3/wrappers/csharp/src/lib/VideoCamera.cs000066400000000000000000000140001264163024100231610ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Collections.Generic; using System.ComponentModel; namespace freenect { /// /// Provides access to the RGB/IR camera on the Kinect /// /// /// public class VideoCamera : BaseCamera { /// /// Gets and sets the current video mode for the video camera. For best results, /// use one of the modes in the VideoCamera.Modes collection. /// public VideoFrameMode Mode { get { return (VideoFrameMode)this.captureMode; } set { this.SetVideoMode(value); } } /// /// Gets a list of available, valid video modes /// public VideoFrameMode[] Modes { get; private set; } /// /// Constructor /// /// /// Parent device that this video camera is part of /// internal VideoCamera(Kinect parent) : base(parent) { // Update modes available for this video camera this.UpdateVideoModes(); // Use the first mode by default this.Mode = this.Modes[0]; // Setup callbacks KinectNative.freenect_set_video_callback(parent.devicePointer, this.DataCallback); } /// /// Starts streaming RGB data from this camera /// public void Start() { // Update image map before starting this.UpdateNextFrameImageMap(); // Start int result = KinectNative.freenect_start_video(this.parentDevice.devicePointer); if(result != 0) { throw new Exception("Could not start video stream. Error Code: " + result); } // All done this.IsRunning = true; } /// /// Stops streaming video data from this camera /// public void Stop() { if(this.IsRunning == false) { // Not running, nothing to do return; } // Stop camera int result = KinectNative.freenect_stop_video(this.parentDevice.devicePointer); if(result != 0) { throw new Exception("Could not stop video stream. Error Code: " + result); } this.IsRunning = false; } /// /// Sets the direct access buffer for the VideoCamera. /// /// /// Pointer to the direct access data buffer for the VideoCamera. /// protected override void SetDataBuffer(IntPtr ptr) { // Save data buffer this.dataBuffer = ptr; // Tell the kinect library about it KinectNative.freenect_set_video_buffer(this.parentDevice.devicePointer, ptr); // update image map this.UpdateNextFrameImageMap(); } /// /// Sets the current video mode /// /// /// Video mode to switch to. /// protected void SetVideoMode(VideoFrameMode mode) { // Is this a different mode? if(this.Mode == mode) { return; } // Stop camera first if running bool running = this.IsRunning; if(running) { this.Stop(); } // Check to make sure mode is valid by finding it again VideoFrameMode foundMode = VideoFrameMode.Find(mode.Format, mode.Resolution); if(foundMode == null) { throw new Exception("Invalid Video Mode: [" + mode.Format + ", " + mode.Resolution + "]"); } // Save mode this.captureMode = mode; // All good, switch to new mode int result = KinectNative.freenect_set_video_mode(this.parentDevice.devicePointer, foundMode.nativeMode); if(result != 0) { throw new Exception("Mode switch failed. Error Code: " + result); } // Update image map this.UpdateNextFrameImageMap(); // If we were running before, start up again if(running) { this.Start(); } } /// /// Updates the next frame imagemap that's waiting for data with any state changes /// protected void UpdateNextFrameImageMap() { if(this.DataBuffer == IntPtr.Zero) { // have to set our own buffer as the video buffer this.nextFrameData = new ImageMap(this.Mode); } else { // already have a buffer from user this.nextFrameData = new ImageMap(this.Mode, this.DataBuffer); } // Set video buffer KinectNative.freenect_set_video_buffer(this.parentDevice.devicePointer, this.nextFrameData.DataPointer); } /// /// Updates list of video modes that this camera has. /// private void UpdateVideoModes() { List modes = new List(); // Get number of modes int numModes = KinectNative.freenect_get_video_mode_count(this.parentDevice.devicePointer); // Go through modes for(int i = 0; i < numModes; i++) { VideoFrameMode mode = (VideoFrameMode)FrameMode.FromInterop(KinectNative.freenect_get_video_mode(i), FrameMode.FrameModeType.VideoFormat); if(mode != null) { modes.Add(mode); } } // All done this.Modes = modes.ToArray(); } } }libfreenect-0.5.3/wrappers/csharp/src/lib/VideoFrameMode.cs000066400000000000000000000042461264163024100236430ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Collections.Generic; namespace freenect { /// /// Depth frame mode. /// public class VideoFrameMode : FrameMode { /// /// Gets the format for this video frame mode /// public VideoFormat Format { get { return this.videoFormat; } } /// /// Ninja constructor /// internal VideoFrameMode() { } /// /// Finds a mode, given a format and resolution. /// /// /// Video format for the mode /// /// /// Resolution for the mode /// /// /// Mode with the format/resolution combo. Null if the combination is invalid. /// public static VideoFrameMode Find(VideoFormat format, Resolution resolution) { return (VideoFrameMode)FrameMode.FromInterop(KinectNative.freenect_find_video_mode(resolution, format), FrameMode.FrameModeType.VideoFormat); } } }libfreenect-0.5.3/wrappers/csharp/src/test/000077500000000000000000000000001264163024100206715ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/000077500000000000000000000000001264163024100231335ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/AssemblyInfo.cs000066400000000000000000000017211264163024100260560ustar00rootroot00000000000000using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("ConsoleTest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/Main.cs000066400000000000000000000060351264163024100243520ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Threading; using freenect; namespace ConsoleTest { /// /// Performs some basic tests on the Kinect device connected to see /// if the wrapper is functioning properly /// /// class MainClass { /// /// Driver /// /// /// A /// public static void Main (string[] args) { Console.WriteLine("----------------------------------------"); Console.WriteLine("| Kinect.NET Wrapper Test |"); Console.WriteLine("----------------------------------------\n"); // Try to get number of devices connected Console.WriteLine(" - Device Count: " + Kinect.DeviceCount); // Do more tests if there are devices present if(Kinect.DeviceCount > 0) { // Try to open a device Kinect k = new Kinect(0); Console.Write(" - Opening device 0..."); k.Open(); Console.WriteLine("Done."); // Try to set LED colors Console.WriteLine(" - LED Testing"); string[] colors = Enum.GetNames(typeof(LEDColor)); foreach(string color in colors) { var c = (LEDColor)Enum.Parse(typeof(LEDColor), color); Console.WriteLine("\t - Setting LED to Color: " + color); k.LED.Color = c; Thread.Sleep(3000); } // Try to control motor Console.WriteLine(" - Motor Testing"); Console.WriteLine("\t - Setting tilt to 1 (should face all the way up)"); k.Motor.Tilt = 1; Thread.Sleep(3000); Console.WriteLine("\t - Setting tilt to -1 (should face all the way down)"); k.Motor.Tilt = -1; Thread.Sleep(3000); Console.WriteLine("\t - Setting tilt to 0 (should be back level)"); k.Motor.Tilt = 0; Thread.Sleep(3000); // Close device Console.Write(" - Closing device 0..."); k.Close(); Console.WriteLine("Done."); } // Shutdown the Kinect context Kinect.Shutdown(); // Pause... Console.ReadKey(true); } } } libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/VS2008/000077500000000000000000000000001264163024100237755ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/VS2008/ConsoleTest.csproj000066400000000000000000000040631264163024100274640ustar00rootroot00000000000000 Debug x86 9.0.21022 2.0 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A} Exe ConsoleTest ConsoleTest v3.5 true full false ..\..\..\..\bin\ DEBUG prompt 4 x86 true none false ..\..\..\..\bin\ prompt 4 x86 true False ..\..\..\..\bin\freenectdotnet.dll AssemblyInfo.cs Main.cs libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/VS2008/ConsoleTest.sln000066400000000000000000000015521264163024100267600ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "ConsoleTest.csproj", "{D5CAFFD9-EC8B-4A16-80C9-48048C85843A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|x86.ActiveCfg = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|x86.Build.0 = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|x86.ActiveCfg = Release|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = ConsoleTest.csproj EndGlobalSection EndGlobal libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/VS2010/000077500000000000000000000000001264163024100237665ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/VS2010/ConsoleTest.csproj000066400000000000000000000114001264163024100274460ustar00rootroot00000000000000 Debug x86 9.0.21022 2.0 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A} Exe ConsoleTest ConsoleTest v3.5 3.5 publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true true full false ..\..\..\..\bin\ DEBUG prompt 4 x86 true AllRules.ruleset none false ..\..\..\..\bin\ prompt 4 x86 true AllRules.ruleset true ..\..\..\..\bin\ DEBUG full x64 prompt AllRules.ruleset false false false ..\..\..\..\bin\ x64 prompt AllRules.ruleset false False ..\..\..\..\bin\freenectdotnet.dll AssemblyInfo.cs Main.cs False .NET Framework 3.5 SP1 Client Profile false False .NET Framework 3.5 SP1 true False Windows Installer 3.1 true libfreenect-0.5.3/wrappers/csharp/src/test/ConsoleTest/VS2010/ConsoleTest.sln000066400000000000000000000036011264163024100267460ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C# Express 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "ConsoleTest.csproj", "{D5CAFFD9-EC8B-4A16-80C9-48048C85843A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|Any CPU.ActiveCfg = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|Mixed Platforms.Build.0 = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|x64.ActiveCfg = Debug|x64 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|x64.Build.0 = Debug|x64 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|x86.ActiveCfg = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Debug|x86.Build.0 = Debug|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|Any CPU.ActiveCfg = Release|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|Mixed Platforms.ActiveCfg = Release|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|x64.ActiveCfg = Release|x64 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|x64.Build.0 = Release|x64 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|x86.ActiveCfg = Release|x86 {D5CAFFD9-EC8B-4A16-80C9-48048C85843A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = ConsoleTest.csproj EndGlobalSection EndGlobal libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/000077500000000000000000000000001264163024100227135ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/MainWindow.UI.cs000066400000000000000000000306431264163024100256400ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using freenect; namespace KinectDemo { public partial class MainWindow : Form { /// /// Initialize UI components /// private void InitializeComponents() { /// /// accelerometerZValueLabel /// this.accelerometerZValueLabel = new Label(); this.accelerometerZValueLabel.Text = "0"; this.accelerometerZValueLabel.Dock = DockStyle.Fill; /// /// accelerometerYValueLabel /// this.accelerometerYValueLabel = new Label(); this.accelerometerYValueLabel.Text = "0"; this.accelerometerYValueLabel.Dock = DockStyle.Fill; /// /// accelerometerXValueLabel /// this.accelerometerXValueLabel = new Label(); this.accelerometerXValueLabel.Text = "0"; this.accelerometerXValueLabel.Dock = DockStyle.Fill; /// /// accelerometerZHeaderLabel /// this.accelerometerZHeaderLabel = new Label(); this.accelerometerZHeaderLabel.Text = "Z:"; this.accelerometerZHeaderLabel.Dock = DockStyle.Fill; this.accelerometerZHeaderLabel.Font = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Bold); /// /// accelerometerYHeaderLabel /// this.accelerometerYHeaderLabel = new Label(); this.accelerometerYHeaderLabel.Text = "Y:"; this.accelerometerYHeaderLabel.Dock = DockStyle.Fill; this.accelerometerYHeaderLabel.Font = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Bold); /// /// accelerometerXHeaderLabel /// this.accelerometerXHeaderLabel = new Label(); this.accelerometerXHeaderLabel.Text = "X:"; this.accelerometerXHeaderLabel.Dock = DockStyle.Fill; this.accelerometerXHeaderLabel.Font = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Bold); /// /// accelerometerStatusTable /// this.accelerometerStatusTable = new TableLayoutPanel(); this.accelerometerStatusTable.RowCount = 3; this.accelerometerStatusTable.ColumnCount = 2; this.accelerometerStatusTable.Dock = DockStyle.Fill; this.accelerometerStatusTable.Controls.Add(this.accelerometerXHeaderLabel, 0, 0); this.accelerometerStatusTable.Controls.Add(this.accelerometerXValueLabel, 1, 0); this.accelerometerStatusTable.Controls.Add(this.accelerometerYHeaderLabel, 0, 1); this.accelerometerStatusTable.Controls.Add(this.accelerometerYValueLabel, 1, 1); this.accelerometerStatusTable.Controls.Add(this.accelerometerZHeaderLabel, 0, 2); this.accelerometerStatusTable.Controls.Add(this.accelerometerZValueLabel, 1, 2); /// /// accelerometerStatusGroup /// this.accelerometerStatusGroup = new GroupBox(); this.accelerometerStatusGroup.Dock = DockStyle.Fill; this.accelerometerStatusGroup.Text = "Accelerometer"; this.accelerometerStatusGroup.Height = 100; this.accelerometerStatusGroup.Padding = new Padding(10); this.accelerometerStatusGroup.Controls.Add(this.accelerometerStatusTable); /// /// selectLEDColorCombo /// this.selectLEDColorCombo = new ComboBox(); this.selectLEDColorCombo.Dock = DockStyle.Fill; this.selectLEDColorCombo.DropDownStyle = ComboBoxStyle.DropDownList; string[] colors = Enum.GetNames(typeof(LEDColor)); for(int i = 0; i < colors.Length; i++) { this.selectLEDColorCombo.Items.Add(colors[i]); } if(colors.Length > 0) { this.selectLEDColorCombo.SelectedIndex = 0; } this.selectLEDColorCombo.SelectedIndexChanged += HandleSelectLEDColorComboSelectedIndexChanged; /// /// ledControlGroup /// this.ledControlGroup = new GroupBox(); this.ledControlGroup.Dock = DockStyle.Left; this.ledControlGroup.Text = "LED"; this.ledControlGroup.Height = 60; this.ledControlGroup.Padding = new Padding(10); this.ledControlGroup.Controls.Add(this.selectLEDColorCombo); /// /// motorCurrentTiltLabel /// this.motorCurrentTiltLabel = new Label(); this.motorCurrentTiltLabel.Dock = DockStyle.Top; this.motorCurrentTiltLabel.TextAlign = ContentAlignment.MiddleLeft; this.motorCurrentTiltLabel.AutoSize = false; this.motorCurrentTiltLabel.Height = 25; this.motorCurrentTiltLabel.Text = "Current Tilt:"; /// /// motorTiltStatusLabel /// this.motorTiltStatusLabel = new Label(); this.motorTiltStatusLabel.Dock = DockStyle.Top; this.motorTiltStatusLabel.TextAlign = ContentAlignment.MiddleLeft; this.motorTiltStatusLabel.AutoSize = false; this.motorTiltStatusLabel.Height = 25; this.motorTiltStatusLabel.Text = "Tilt Status:"; /// /// motorTiltUpDown /// this.motorTiltUpDown = new NumericUpDown(); this.motorTiltUpDown.Dock = DockStyle.Top; this.motorTiltUpDown.AutoSize = false; this.motorTiltUpDown.Height = 35; this.motorTiltUpDown.DecimalPlaces = 1; this.motorTiltUpDown.Minimum = -1.0m; this.motorTiltUpDown.Maximum = 1.0m; this.motorTiltUpDown.Increment = 0.1m; this.motorTiltUpDown.ValueChanged += HandleMotorTiltUpDownValueChanged; /// /// motorControlGroup /// this.motorControlGroup = new GroupBox(); this.motorControlGroup.Dock = DockStyle.Left; this.motorControlGroup.Text = "Motor"; this.motorControlGroup.Height = 105; this.motorControlGroup.Padding = new Padding(10); this.motorControlGroup.Controls.Add(this.motorTiltStatusLabel); this.motorControlGroup.Controls.Add(this.motorCurrentTiltLabel); this.motorControlGroup.Controls.Add(this.motorTiltUpDown); /// /// selectDepthModeLabel /// this.selectDepthModeLabel = new Label(); this.selectDepthModeLabel.Text = "Depth Mode:"; this.selectDepthModeLabel.Dock = DockStyle.Top; this.selectDepthModeLabel.TextAlign = ContentAlignment.MiddleLeft; /// /// selectDepthModeCombo /// this.selectDepthModeCombo = new ComboBox(); this.selectDepthModeCombo.Dock = DockStyle.Top; this.selectDepthModeCombo.DropDownStyle = ComboBoxStyle.DropDownList; this.selectDepthModeCombo.SelectedIndexChanged += HandleSelectDepthModeComboSelectedIndexChanged; /// /// selectVideoModeLabel /// this.selectVideoModeLabel = new Label(); this.selectVideoModeLabel.Text = "Video Mode:"; this.selectVideoModeLabel.Dock = DockStyle.Top; this.selectVideoModeLabel.TextAlign = ContentAlignment.MiddleLeft; /// /// selectVideoModeCombo /// this.selectVideoModeCombo = new ComboBox(); this.selectVideoModeCombo.Dock = DockStyle.Top; this.selectVideoModeCombo.DropDownStyle = ComboBoxStyle.DropDownList; this.selectVideoModeCombo.SelectedIndexChanged += HandleSelectVideoModeComboSelectedIndexChanged;; /// /// selectVideoModeGroup /// this.selectVideoModeGroup = new GroupBox(); this.selectVideoModeGroup.Dock = DockStyle.Left; this.selectVideoModeGroup.Height = 130; this.selectVideoModeGroup.Text = "Select Modes"; this.selectVideoModeGroup.Padding = new Padding(10); this.selectVideoModeGroup.Controls.Add(this.selectDepthModeCombo); this.selectVideoModeGroup.Controls.Add(this.selectDepthModeLabel); this.selectVideoModeGroup.Controls.Add(this.selectVideoModeCombo); this.selectVideoModeGroup.Controls.Add(this.selectVideoModeLabel); this.selectVideoModeGroup.Enabled = false; /// /// controlsPanel /// this.controlsPanel = new Panel(); this.controlsPanel.Dock = DockStyle.Bottom; this.controlsPanel.Padding = new Padding(7); this.controlsPanel.Height = 150; this.controlsPanel.Controls.Add(this.accelerometerStatusGroup); this.controlsPanel.Controls.Add(this.ledControlGroup); this.controlsPanel.Controls.Add(this.motorControlGroup); this.controlsPanel.Controls.Add(this.selectVideoModeGroup); /// /// previewControl /// this.previewControl = new PreviewControl(); this.previewControl.Dock = DockStyle.Fill; /// /// contentPanel /// this.contentPanel = new Panel(); this.contentPanel.Dock = DockStyle.Fill; this.contentPanel.Controls.Add(this.previewControl); this.contentPanel.Controls.Add(this.controlsPanel); /// /// aboutButton /// this.aboutButton = new ToolStripButton(); this.aboutButton.Text = "About"; this.aboutButton.Padding = new Padding(7, 0, 7, 0); this.aboutButton.Margin = new Padding(10, 7, 0, 7); this.aboutButton.Click += HandleAboutButtonClick; /// /// disconnectButton /// this.disconnectButton = new ToolStripButton(); this.disconnectButton.Text = "Disconnect"; this.disconnectButton.Padding = new Padding(7, 0, 7, 0); this.disconnectButton.Margin = new Padding(10, 7, 0, 7); this.disconnectButton.Visible = false; this.disconnectButton.Click += HandleDisconnectButtonClick; /// /// refreshButton /// this.refreshButton = new ToolStripButton(); this.refreshButton.Text = "Refresh"; this.refreshButton.Padding = new Padding(7, 0, 7, 0); this.refreshButton.Margin = new Padding(10, 7, 0, 7); this.refreshButton.Click += HandleRefreshButtonClick; /// /// connectButton /// this.connectButton = new ToolStripButton(); this.connectButton.Text = "Connect"; this.connectButton.Padding = new Padding(7, 0, 7, 0); this.connectButton.Margin = new Padding(10, 7, 0, 7); this.connectButton.Click += HandleConnectButtonClick; /// /// selectDeviceCombo /// this.selectDeviceCombo = new ToolStripComboBox(); this.selectDeviceCombo.Width = 150; this.selectDeviceCombo.Margin = new Padding(7, 0, 0, 0); this.selectDeviceCombo.DropDownStyle = ComboBoxStyle.DropDownList; /// /// mainToolbar /// this.mainToolbar = new ToolStrip(); this.mainToolbar.Dock = DockStyle.Top; this.mainToolbar.GripStyle = ToolStripGripStyle.Hidden; this.mainToolbar.AutoSize = false; this.mainToolbar.Height = 35; this.mainToolbar.Items.Add(this.selectDeviceCombo); this.mainToolbar.Items.Add(this.refreshButton); this.mainToolbar.Items.Add(this.connectButton); this.mainToolbar.Items.Add(this.disconnectButton); this.mainToolbar.Items.Add(this.aboutButton); /// /// MainWindow /// this.Width = 1280; this.Height = 630; this.Text = "Kinect.NET Demo"; this.Font = new Font(this.Font.FontFamily, 9.0f); this.Controls.Add(this.contentPanel); this.Controls.Add(this.mainToolbar); this.FormClosing += HandleFormClosing; } /// /// UI Components /// private ToolStrip mainToolbar; private Panel controlsPanel; private Panel contentPanel; private PreviewControl previewControl; private GroupBox motorControlGroup; private NumericUpDown motorTiltUpDown; private Label motorCurrentTiltLabel; private Label motorTiltStatusLabel; private GroupBox accelerometerStatusGroup; private TableLayoutPanel accelerometerStatusTable; private Label accelerometerXHeaderLabel; private Label accelerometerYHeaderLabel; private Label accelerometerZHeaderLabel; private Label accelerometerXValueLabel; private Label accelerometerYValueLabel; private Label accelerometerZValueLabel; private GroupBox ledControlGroup; private ComboBox selectLEDColorCombo; private ToolStripComboBox selectDeviceCombo; private ToolStripButton refreshButton; private ToolStripButton connectButton; private ToolStripButton disconnectButton; private ToolStripButton aboutButton; private GroupBox selectVideoModeGroup; private ComboBox selectVideoModeCombo; private Label selectVideoModeLabel; private ComboBox selectDepthModeCombo; private Label selectDepthModeLabel; } }libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/MainWindow.cs000066400000000000000000000365741264163024100253350ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.Threading; using freenect; using System.Drawing; using System.Diagnostics; namespace KinectDemo { public partial class MainWindow : Form { /// /// Current kinect device /// private Kinect kinect = null; /// /// Update timer for tilt/motor status /// private System.Windows.Forms.Timer statusUpdateTimer = new System.Windows.Forms.Timer(); /// /// Is a device connected and running? /// private volatile bool isRunning = false; /// /// Thread for updating status and letting kinect process events /// private Thread updateThread = null; /// /// Constructor /// public MainWindow() { // Initialize UI stuff this.InitializeComponents(); // Initialize update timer this.statusUpdateTimer.Interval = 1000; this.statusUpdateTimer.Tick += this.HandleStatusUpdateTimerTick; // Update device list this.UpdateDeviceList(); } /// /// Updates the list of devices shown in the GUI /// private void UpdateDeviceList() { // Clear old this.selectDeviceCombo.Items.Clear(); // Get count int deviceCount = Kinect.DeviceCount; // Fill in combo box for(int i = 0; i < deviceCount; i++) { this.selectDeviceCombo.Items.Add("Device " + i); } // Do we have anything to auto-select? if(deviceCount > 0) { this.selectDeviceCombo.SelectedIndex = 0; // Enable buttons this.connectButton.Visible = this.connectButton.Enabled = true; this.disconnectButton.Visible = false; } else { // Disable buttons this.connectButton.Visible = false; this.disconnectButton.Visible = false; } } /// /// Update list of modes /// private void UpdateModeList() { // Go through video modes and add em this.selectVideoModeCombo.Items.Clear(); this.selectVideoModeCombo.Items.Add("Disabled"); foreach(var mode in this.kinect.VideoCamera.Modes) { if(mode.Format == VideoFormat.RGB || mode.Format == VideoFormat.Infrared8Bit || mode.Format == VideoFormat.Infrared10Bit) { this.selectVideoModeCombo.Items.Add(mode); } } // Autoselect first mode if(this.kinect.VideoCamera.Modes.Length > 0) { this.selectVideoModeCombo.SelectedIndex = 2; } // Go through depth modes and add em this.selectDepthModeCombo.Items.Clear(); this.selectDepthModeCombo.Items.Add("Disabled"); foreach(var mode in this.kinect.DepthCamera.Modes) { if(mode.Format == DepthFormat.Depth10Bit || mode.Format == DepthFormat.Depth11Bit) { this.selectDepthModeCombo.Items.Add(mode); } } // Autoselect first mode if(this.kinect.DepthCamera.Modes.Length > 0) { this.selectDepthModeCombo.SelectedIndex = 1; } } /// /// Connects to the specified device /// private void Connect(int deviceID) { // If a device is already connected, disconnect if(this.isRunning) { this.Disconnect(); } // Now running this.isRunning = true; // Create instance this.kinect = new Kinect(deviceID); // Open kinect this.kinect.Open(); // Set tilt to 0 to start with this.motorTiltUpDown.Value = 0; // Setup image handlers this.kinect.VideoCamera.DataReceived += HandleKinectVideoCameraDataReceived; this.kinect.DepthCamera.DataReceived += HandleKinectDepthCameraDataReceived; // LED is set to none to start this.kinect.LED.Color = LEDColor.None; this.selectLEDColorCombo.SelectedIndex = 0; // Update video/depth modes this.UpdateModeList(); // Enable video/depth mode chooser this.selectVideoModeGroup.Enabled = true; // Setup update thread this.updateThread = new Thread(delegate() { while(this.isRunning) { try { // Update instance's status this.kinect.UpdateStatus(); // Let preview control render another frame this.previewControl.Render(); Kinect.ProcessEvents(); } catch(ThreadInterruptedException e) { return; } catch(Exception ex) { } } }); // Start updating status this.statusUpdateTimer.Enabled = true; // Disable connect button and enable the disconnect one this.disconnectButton.Visible = true; this.connectButton.Visible = false; this.refreshButton.Visible = false; this.selectDeviceCombo.Enabled = false; // Enable content areas this.contentPanel.Enabled = true; // Start update thread this.updateThread.Start(); } /// /// Disconnects from teh currently connected Kinect device /// private void Disconnect() { // Are we running? if(this.isRunning == false) { return; } // Stop updating status this.statusUpdateTimer.Enabled = false; // No longer running this.isRunning = false; // Wait till update thread closes down this.updateThread.Interrupt(); this.updateThread.Join(); this.updateThread = null; // Disconnect from the kinect this.kinect.Close(); this.kinect = null; // Disable video/depth mode chooser this.selectVideoModeGroup.Enabled = false; // Disable disconnect button and enable the connect/refresh ones this.disconnectButton.Visible = false; this.connectButton.Visible = true; this.refreshButton.Visible = true; this.selectDeviceCombo.Enabled = true; // Disable content areas this.contentPanel.Enabled = false; } /// /// /// /// /// A /// /// /// A /// private void HandleKinectDepthCameraDataReceived (object sender, DepthCamera.DataReceivedEventArgs e) { this.previewControl.HandleDepthBackBufferUpdate(); this.kinect.DepthCamera.DataBuffer = this.previewControl.DepthBackBuffer; } /// /// /// /// /// A /// /// /// A /// private void HandleKinectVideoCameraDataReceived (object sender, VideoCamera.DataReceivedEventArgs e) { this.previewControl.HandleVideoBackBufferUpdate(); this.kinect.VideoCamera.DataBuffer = this.previewControl.VideoBackBuffer; } /// /// Update status panes /// /// /// A /// /// /// A /// private void HandleStatusUpdateTimerTick (object sender, EventArgs e) { this.motorCurrentTiltLabel.Text = "Current Tilt: " + this.kinect.Motor.Tilt; this.motorTiltStatusLabel.Text = "Tilt Status: " + this.kinect.Motor.TiltStatus.ToString(); this.accelerometerXValueLabel.Text = Math.Round(this.kinect.Accelerometer.X, 2).ToString(); this.accelerometerYValueLabel.Text = Math.Round(this.kinect.Accelerometer.Y, 2).ToString(); this.accelerometerZValueLabel.Text = Math.Round(this.kinect.Accelerometer.Z, 2).ToString(); this.Text = "Kinect.NET Demo - Video FPS: " + this.previewControl.VideoFPS + " | Depth FPS: " + this.previewControl.DepthFPS; } /// /// Selected different LED color /// /// /// A /// /// /// A /// private void HandleSelectLEDColorComboSelectedIndexChanged (object sender, EventArgs e) { this.kinect.LED.Color = (LEDColor)Enum.Parse(typeof(LEDColor), this.selectLEDColorCombo.SelectedItem.ToString()); } /// /// Motor tilt changed /// /// /// A /// /// /// A /// private void HandleMotorTiltUpDownValueChanged (object sender, EventArgs e) { this.kinect.Motor.Tilt = (double)this.motorTiltUpDown.Value; } /// /// Handle form being closed. Here we make sure we are closed down /// /// /// A /// /// /// A /// private void HandleFormClosing (object sender, FormClosingEventArgs e) { this.Disconnect(); } /// /// Handle refresh button /// /// /// A /// /// /// A /// private void HandleRefreshButtonClick (object sender, EventArgs e) { this.UpdateDeviceList(); } /// /// Handle connnect button /// /// /// A /// /// /// A /// private void HandleConnectButtonClick (object sender, EventArgs e) { this.Connect(this.selectDeviceCombo.SelectedIndex); } /// /// Handle disconnect button /// /// /// A /// /// /// A /// private void HandleDisconnectButtonClick (object sender, EventArgs e) { this.Disconnect(); } /// /// Handle about button /// /// /// A /// /// /// A /// private void HandleAboutButtonClick (object sender, EventArgs e) { new AboutWindow().ShowDialog(); } /// /// Handle depth mode being changed /// /// /// A /// /// /// A /// private void HandleSelectDepthModeComboSelectedIndexChanged (object sender, EventArgs e) { // Check to see if we are actually connected if(this.isRunning == false) { // Not running, shouldn't even be here return; } // Get index selected int index = this.selectDepthModeCombo.SelectedIndex; // 0 means "Disabled", otherwise, it's a depth format if(index == 0) { this.kinect.DepthCamera.Stop(); } else if(index > 0) { var mode = (DepthFrameMode)this.selectDepthModeCombo.SelectedItem; this.kinect.DepthCamera.Stop(); this.kinect.DepthCamera.Mode = mode; this.previewControl.DepthMode = mode; // Start up camera again this.kinect.DepthCamera.Start(); } } /// /// Handle video mode being changed /// /// /// A /// /// /// A /// private void HandleSelectVideoModeComboSelectedIndexChanged (object sender, EventArgs e) { // Check to see if we are actually connected if(this.isRunning == false) { // Not running, shouldn't even be here return; } // Get index selected int index = this.selectVideoModeCombo.SelectedIndex; // 0 means "Disabled", otherwise, it's a depth format if(index == 0) { // Disabled this.kinect.VideoCamera.Stop(); } else if(index > 0) { var mode = (VideoFrameMode)this.selectVideoModeCombo.SelectedItem; this.kinect.VideoCamera.Stop(); this.kinect.VideoCamera.Mode = mode; this.previewControl.VideoMode = mode; // Start up camera again this.kinect.VideoCamera.Start(); } } /// /// /// /// /// A /// /// /// A /// private void HandleDepthPreviewWindowFormClosing (object sender, FormClosingEventArgs e) { e.Cancel = true; this.selectDepthModeCombo.SelectedIndex = 0; } /// /// /// /// /// A /// /// /// A /// private void HandleVideoPreviewWindowFormClosing (object sender, FormClosingEventArgs e) { e.Cancel = true; this.selectVideoModeCombo.SelectedIndex = 0; } /// /// About Window /// private class AboutWindow : Form { public AboutWindow() { /// /// linkLabel /// LinkLabel linkLabel = new LinkLabel(); linkLabel.Text = "openkinect.org"; linkLabel.Click += delegate(object sender, EventArgs e) { Process.Start("http://openkinect.org/wiki/CSharp_Wrapper"); }; linkLabel.Dock = DockStyle.Top; /// /// authorLabel /// Label authorLabel = new Label(); authorLabel.Text = "by Aditya Gaddam"; authorLabel.Dock = DockStyle.Top; /// /// titleLabel /// Label titleLabel = new Label(); titleLabel.Text = "Kinect.NET Demo"; titleLabel.Font = new Font(this.Font.FontFamily, 14.0f); titleLabel.Dock = DockStyle.Top; /// /// logoImageBox /// PictureBox logoPictureBox = new PictureBox(); logoPictureBox.Image = Image.FromFile("openkinect_logo.png"); logoPictureBox.Dock = DockStyle.Left; logoPictureBox.Width = 96; /// /// aboutContentPanel /// Panel aboutContentPanel = new Panel(); aboutContentPanel.Dock = DockStyle.Fill; aboutContentPanel.Controls.Add(linkLabel); aboutContentPanel.Controls.Add(authorLabel); aboutContentPanel.Controls.Add(titleLabel); aboutContentPanel.Padding = new Padding(7, 0, 0, 0); /// /// AboutWindow /// this.ShowInTaskbar = false; //this.FormBorderStyle = FormBorderStyle.FixedSingle; this.MinimizeBox = false; this.MaximizeBox = false; this.StartPosition = FormStartPosition.CenterScreen; this.Text = "About"; this.Width = 350; this.Height = 140; this.Font = new System.Drawing.Font(this.Font.FontFamily, 9.0f); this.BackColor = Color.White; this.Controls.Add(aboutContentPanel); this.Controls.Add(logoPictureBox); this.Padding = new Padding(7); } } } }libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/PreviewControl.UI.cs000066400000000000000000000036421264163024100265450ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using freenect; using OpenTK; using OpenTK.Graphics.OpenGL; using System.Drawing; namespace KinectDemo { /// /// Displays video / depth data /// public partial class PreviewControl : UserControl { /// /// Initialize UI components /// public void InitializeComponents() { /// /// renderPanel /// this.renderPanel = new OpenTK.GLControl(); this.renderPanel.Dock = DockStyle.Fill; this.renderPanel.Load += HandleRenderPanelLoad; this.renderPanel.Paint += HandleRenderPanelPaint; /// /// PreviewWindow /// this.BackColor = Color.Blue; this.Controls.Add(this.renderPanel); } /// /// UI Components /// protected OpenTK.GLControl renderPanel; } }libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/PreviewControl.cs000066400000000000000000000305741264163024100262350ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using freenect; using OpenTK; using OpenTK.Graphics.OpenGL; using System.Drawing; using System.Threading; namespace KinectDemo { /// /// Displays video / depth data /// public partial class PreviewControl : UserControl { /// /// Gets or sets the current frame mode for the video feed /// public VideoFrameMode VideoMode { get { return this.videoMode; } set { // Make sure we are actually changing something if(this.videoMode == value) { return; } // Resize buffer if(this.videoDataBuffers != null) { this.videoDataBuffers.Dispose(); } this.videoDataBuffers = new SwapBufferCollection(3, 3 * value.Width * value.Height); // Save mode this.videoMode = value; } } /// /// Gets or sets the current frame mode for the depth feed /// public DepthFrameMode DepthMode { get { return this.depthMode; } set { // Make sure we are actually changing something if(this.depthMode == value) { return; } // Resize buffer if(this.depthDataBuffers != null) { this.depthDataBuffers.Dispose(); } this.depthDataBuffers = new SwapBufferCollection(3, 3 * value.Width * value.Height); // Save mode this.depthMode = value; } } /// /// Handle to back buffer for the video feed /// public IntPtr VideoBackBuffer { get { return this.videoDataBuffers.GetHandle(2); } } /// /// Handle to back buffer for the depth feed /// public IntPtr DepthBackBuffer { get { return this.depthDataBuffers.GetHandle(2); } } /// /// Gets the FPS for the depth feed /// public int DepthFPS { get; private set; } /// /// Gets the FPS for the video feed /// public int VideoFPS { get; private set; } /// /// Video mode /// private VideoFrameMode videoMode = null; /// /// Depth mode /// private DepthFrameMode depthMode = null; /// /// Texture for depth data /// private uint depthTexture; /// /// Texture for video data /// private uint videoTexture; /// /// Swappable data buffers for depth data /// private SwapBufferCollection depthDataBuffers; /// /// Swappable data buffers for video data /// private SwapBufferCollection videoDataBuffers; /// /// Is new video data pending? /// private bool videoDataPending = false; /// /// Is new depth data pending? /// private bool depthDataPending = false; // Gamma constants for color map generation private UInt16[] gamma = new UInt16[2048]; /// /// Last time FPS was updated for Depth /// private DateTime lastDepthFPSUpate = DateTime.Now; /// /// Number of frames since last FPS update for depth /// private int depthFrameCount = 0; /// /// Last time FPS was updated for video /// private DateTime lastVideoFPSUpdate = DateTime.Now; /// /// Number of frames since last FPS update for video /// private int videoFrameCount = 0; /// /// Constructor /// public PreviewControl() { // Initialize UI components this.InitializeComponents(); // Caluclate gamma constants for (int i = 0 ; i < 2048; i++) { double v = i / 2048.0; v = Math.Pow((double)v, 3.0) * 6.0; gamma[i] = (UInt16)(v * 6.0 * 256.0); } } /// /// Handle video data being updated /// public void HandleVideoBackBufferUpdate() { // Swap middle and back buffers if(this.VideoMode.Format == VideoFormat.Infrared10Bit) { // Swap mid and back unsafe { Int16 *ptrMid = (Int16 *)this.videoDataBuffers.GetHandle(1); Int16 *ptrBack = (Int16 *)this.videoDataBuffers.GetHandle(2); int dim = this.VideoMode.Width * this.VideoMode.Height; int i = 0; Int16 mult = 50; for (i = 0; i < dim; i++) { *ptrMid++ = (Int16)(ptrBack[i] * mult); } } } else { this.videoDataBuffers.Swap(1, 2); } // Calculate FPS this.videoFrameCount++; if((DateTime.Now - this.lastVideoFPSUpdate).Seconds >= 1) { this.VideoFPS = this.videoFrameCount; this.videoFrameCount = 0; this.lastVideoFPSUpdate = DateTime.Now; } // New data! this.videoDataPending = true; } /// /// Handle depth data being updated /// public void HandleDepthBackBufferUpdate() { // Swap mid and back unsafe { byte *ptrMid = (byte *)this.depthDataBuffers.GetHandle(1); Int16 *ptrBack = (Int16 *)this.depthDataBuffers.GetHandle(2); int dim = this.DepthMode.Width * this.DepthMode.Height; int i = 0; Int16 pval = 0; Int16 lb = 0; for (i = 0; i < dim; i++) { pval = (Int16)this.gamma[ptrBack[i]]; lb = (Int16)(pval & 0xff); switch (pval>>8) { case 0: *ptrMid++ = 255; *ptrMid++ = (byte)(255 - lb); *ptrMid++ = (byte)(255 - lb); break; case 1: *ptrMid++ = 255; *ptrMid++ = (byte)lb; *ptrMid++ = 0; break; case 2: *ptrMid++ = (byte)(255 - lb); *ptrMid++ = 255; *ptrMid++ = 0; break; case 3: *ptrMid++ = 0; *ptrMid++ = 255; *ptrMid++ = (byte)lb; break; case 4: *ptrMid++ = 0; *ptrMid++ = (byte)(255 - lb); *ptrMid++ = 255; break; case 5: *ptrMid++ = 0; *ptrMid++ = 0; *ptrMid++ = (byte)(255 - lb); break; default: *ptrMid++ = 0; *ptrMid++ = 0; *ptrMid++ = 0; break; } } } // Calculate FPS this.depthFrameCount++; if((DateTime.Now - this.lastDepthFPSUpate).Seconds >= 1) { this.DepthFPS = this.depthFrameCount; this.depthFrameCount = 0; this.lastDepthFPSUpate = DateTime.Now; } // New data! this.depthDataPending = true; } /// /// Make the preview control render a frame /// public void Render() { this.renderPanel.Invalidate(); } /// /// Handle render panel OnPaint /// /// /// A /// /// /// A /// private void HandleRenderPanelPaint(object sender, PaintEventArgs e) { // Init GL window for render GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.LoadIdentity(); GL.ClearColor(Color.Blue); GL.Enable(EnableCap.Texture2D); /// Render video this.HandleRenderPanelPaintVideo(); // Render depth this.HandleRenderPanelPaintDepth(); // Present this.renderPanel.SwapBuffers(); } /// /// Render video feed /// private void HandleRenderPanelPaintVideo() { if(this.VideoMode == null) { // Not rendering anything return; } if(this.videoDataPending) { // Swap middle and front buffers (we will be rendering off of front buffer) this.videoDataBuffers.Swap(0, 1); } // Use preview texture for rendering GL.BindTexture(TextureTarget.Texture2D, this.videoTexture); // Setup texture VideoFormat format = this.VideoMode.Format; switch(format) { case VideoFormat.RGB: GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Three, this.VideoMode.Width, this.VideoMode.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.UnsignedByte, this.videoDataBuffers.GetHandle(0)); break; case VideoFormat.Infrared8Bit: GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.One, this.VideoMode.Width, this.VideoMode.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Luminance, PixelType.UnsignedByte, this.videoDataBuffers.GetHandle(0)); break; case VideoFormat.Infrared10Bit: GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Luminance16, this.VideoMode.Width, this.VideoMode.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Luminance, PixelType.UnsignedShort, this.videoDataBuffers.GetHandle(0)); break; } // Draw texture GL.Begin(BeginMode.TriangleFan); GL.Color4(255.0f, 255.0f, 255.0f, 255.0f); GL.TexCoord2(0, 0); GL.Vertex3(0, 0, 0); GL.TexCoord2(1, 0); GL.Vertex3(640, 0, 0); GL.TexCoord2(1, 1); GL.Vertex3(640, 480, 0); GL.TexCoord2(0, 1); GL.Vertex3(0, 480, 0); GL.End(); // Video data not pending anymore this.videoDataPending = false; } /// /// Render depth feed /// private void HandleRenderPanelPaintDepth() { if(this.DepthMode == null) { // Not rendering anything return; } if(this.depthDataPending) { // Swap front and middle buffers this.depthDataBuffers.Swap(0, 1); } // Use preview texture for rendering GL.BindTexture(TextureTarget.Texture2D, this.depthTexture); // Setup texture GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Three, this.DepthMode.Width, this.DepthMode.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.UnsignedByte, this.depthDataBuffers.GetHandle(0)); // Draw texture GL.Begin(BeginMode.TriangleFan); GL.Color4(255.0f, 255.0f, 255.0f, 255.0f); GL.TexCoord2(0, 0); GL.Vertex3(640, 0, 0); GL.TexCoord2(1, 0); GL.Vertex3(1280, 0, 0); GL.TexCoord2(1, 1); GL.Vertex3(1280, 480, 0); GL.TexCoord2(0, 1); GL.Vertex3(640, 480, 0); GL.End(); // Depth data handled this.depthDataPending = false; } /// /// Handle render panel on load /// /// /// A /// /// /// A /// private void HandleRenderPanelLoad(object sender, EventArgs e) { GL.ClearColor(Color.Blue); GL.ClearDepth(1.0); GL.DepthFunc(DepthFunction.Less); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.ShadeModel(ShadingModel.Smooth); GL.GenTextures(1, out this.videoTexture); GL.BindTexture(TextureTarget.Texture2D, this.videoTexture); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.GenTextures(1, out this.depthTexture); GL.BindTexture(TextureTarget.Texture2D, this.depthTexture); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.Viewport(0, 0, 1280, 480); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); GL.Ortho(0, 1280, 480, 0, -1.0f, 1.0f); GL.MatrixMode(MatrixMode.Modelview); } } }libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/Program.cs000066400000000000000000000030211264163024100246450ustar00rootroot00000000000000/* * This file is part of the OpenKinect Project. http://www.openkinect.org * * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file * for details. * * This code is licensed to you under the terms of the Apache License, version * 2.0, or, at your option, the terms of the GNU General Public License, * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, * or the following URLs: * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/gpl-2.0.txt * * If you redistribute this file in source form, modified or unmodified, you * may: * 1) Leave this header intact and distribute it under the same terms, * accompanying it with the APACHE20 and GPL20 files, or * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file * In all cases you must keep the copyright notice intact and include a copy * of the CONTRIB file. * * Binary distributions must follow the binary distribution requirements of * either License. */ using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace KinectDemo { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainWindow()); } } } libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/VS2008/000077500000000000000000000000001264163024100235555ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/VS2008/KinectDemo.csproj000066400000000000000000000062721264163024100270300ustar00rootroot00000000000000 Debug x86 9.0.21022 2.0 {2EBB5F0B-9C65-4777-8B0C-76A83867C650} Exe KinectDemo KinectDemo v3.5 true full false ..\..\..\..\bin DEBUG prompt 4 x86 false true /d:TRACE none false ..\..\..\..\bin prompt 4 x86 false true Program.cs MainWindow.cs MainWindow.UI.cs PreviewControl.cs PreviewControl.UI.cs False ..\..\..\..\support\OpenTK.GLControl.dll False ..\..\..\..\support\OpenTK.dll False ..\..\..\..\bin\freenectdotnet.dll openkinect_logo.png PreserveNewest libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/VS2008/KinectDemo.sln000066400000000000000000000015471264163024100263240ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KinectDemo", "KinectDemo.csproj", "{2EBB5F0B-9C65-4777-8B0C-76A83867C650}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|x86.ActiveCfg = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|x86.Build.0 = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|x86.ActiveCfg = Release|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = KinectDemo.csproj EndGlobalSection EndGlobal libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/VS2010/000077500000000000000000000000001264163024100235465ustar00rootroot00000000000000libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/VS2010/KinectDemo.csproj000066400000000000000000000141351264163024100270160ustar00rootroot00000000000000 Debug x86 9.0.21022 2.0 {2EBB5F0B-9C65-4777-8B0C-76A83867C650} Exe KinectDemo KinectDemo v3.5 3.5 publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true true full false ..\..\..\..\bin DEBUG prompt 4 x86 false true AllRules.ruleset none false ..\..\..\..\bin prompt 4 x86 false true AllRules.ruleset true ..\..\..\..\bin\ DEBUG true full x64 prompt AllRules.ruleset false false ..\..\..\..\bin\ true x64 prompt AllRules.ruleset false false Program.cs MainWindow.cs Form MainWindow.UI.cs Form PreviewControl.cs UserControl PreviewControl.UI.cs UserControl False ..\..\..\..\bin\freenectdotnet.dll False ..\..\..\..\support\OpenTK.GLControl.dll False ..\..\..\..\support\OpenTK.dll False .NET Framework 3.5 SP1 Client Profile false False .NET Framework 3.5 SP1 true False Windows Installer 3.1 true openkinect_logo.png Always libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/VS2010/KinectDemo.sln000066400000000000000000000041621264163024100263110ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C# Express 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KinectDemo", "KinectDemo.csproj", "{2EBB5F0B-9C65-4777-8B0C-76A83867C650}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|Any CPU.ActiveCfg = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|Any CPU.Build.0 = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|Mixed Platforms.Build.0 = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|x64.ActiveCfg = Debug|x64 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|x64.Build.0 = Debug|x64 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|x86.ActiveCfg = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Debug|x86.Build.0 = Debug|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|Any CPU.ActiveCfg = Release|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|Any CPU.Build.0 = Release|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|Mixed Platforms.ActiveCfg = Release|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|Mixed Platforms.Build.0 = Release|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|x64.ActiveCfg = Release|x64 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|x64.Build.0 = Release|x64 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|x86.ActiveCfg = Release|x86 {2EBB5F0B-9C65-4777-8B0C-76A83867C650}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = KinectDemo.csproj EndGlobalSection EndGlobal libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/openkinect_icon.ico000066400000000000000000054000261264163024100265650ustar00rootroot00000000000000 hf @@ (Bv (W ( _ ((  Kb2   $Z+q  1  >d0 * N'D (  O'Ed1  *DEs7 ~<Ee2>EED 0DEf3f2EEEE6 8 EEg3 &DEEEE;"5#CEk8d6EEEE6'0>5'tAE&uA;;;;;;%%%111:>;!CEED;<;000BCB?WHE*yEHHHHHH...QDDD@UHEE4jGHHH;;;OOOUUU9sM.}JUUUUUU666555UUU=oN+ITUTUUUEEE[[[bbbbbbSl\bbbbbb???NNNabb_cabbbbbbQQQdddoooooooooooooooIII$$$?fffoooooooooSSSJJJooossssssssskkkCCCD''''bbbsssrrraaa666L( @ xmz'z}2  n4 4  p5E4>  < 3 Y+EE5   b/EB   +DEE6  <EEEr6  v8EEE6 L BEEEE5  *EEEE7   v8EEEEEq6  Y,EEEE8  S*EEEEEED |;EEEE9  [ /DEEEEEEE=" DEEEE:! 0 >EEEEEEEEU+ EEEEE:! i3EEEEEEEEEc2 #EEEEE;" D%EEEEEEEEEEg3 EEEEE<# 3DEEEEEEEEEa1 CEEEE=$V-EEEEEEEEER+ ***{?EEEE%K2*******************,* ~@EEEEEEEE&I2******///888*d>EEEE.U<888888888888'''_0008888884D:DEEEEEED6<8888888$$$555???:I?DEEE3Y@????????????,,,>>>??????2]AEEEEEE(uB?????????(((;;;EEEEEE)xEEEE7^DEEEEEEEEEEEE000(((EEEEEEEEE*wEEEEEE=SEEEEEEEEEE,,,@@@LLLLLLEUKEEE>> ---XXXXXXXXX:tN!FOaUXXXXXXXXXXXXXXX888QQQ_______________=yRIoV____________BBB9HHH______^__Ve\__________________===WWWeeeeeeeeeeeeeeeeeecfdeeeeeeeeeeeeGGG___eeeeeeeeeeeeeeeeeeeeeeeeeee@@@VVVlllllllllllllllllllllllllllllllllLLL000lllllllllllllllllllllllllll:::999kkkrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrPPP+NNNrrrrrrrrrrrrrrrrrrrrrlllxK+++qqqxxxxxxxxxxxxxxxxxxxxxxxxxxxTTTqlllxxxxxxxxxxxxxxxqqq+++K???eeemmmmmmmmmmmmmmmmmmmmmmmm>>>GVVVmmmmmmmmmkkkWWW---(@ 5'8(8*( .( (EY(9((T(((c >(  =a/( $@Ea/(s  ! !AEEa/(+N&B % >EEEa/( )DE@  u7EEEEb/ (  =EEEy9  R)EEEEEb0 (6 d0EEEEEX+  %DEEEEEb0 (  = EEEEEED+  v8EEEEEEb0 ( BEEEEEEE{:  8EEEEEEEb0 (C w9EEEEEEEEE>!  z:EEEEEEEc0 ( S*EEEEEEEEEE<  .EEEEEEEEc0 ( /DEEEEEEEEEEE5  c1EEEEEEEEc1 (R ?EEEEEEEEEEEEj3 BEEEEEEEEc1( i3EEEEEEEEEEEEEC4EEEEEEEEEc1( C$EEEEEEEEEEEEEEE; W,EEEEEEEEEd1(`#CEEEEEEEEEEEEEEE^/t8EEEEEEEEEd1(z:EEEEEEEEEEEEEEEE{;BEEEEEEEEEd2( Y-EEEEEEEEEEEEEEEEECEEEEEEEEEEd2(p5DEEEEEEEEEEEEEEEEEE")EEEEEEEEEEd2Q@EEEEEEEEEEEEEEEEEEE/2EEEEEEEEEEe2n5EEEEEEEEEEEEEEEEEEEE8!6 EEEEEEEEEEe2J'EEEEEEEEEEEEEEEEEEEEE<" 5 EEEEEEEEEEe3&CEEEEEEEEEEEEEEEEEEEEE;" /EEEEEEEEEEe3j|;EEEEEEEEEEEEEEEEEEEEE6  %EEEEEEEEEEe3( (CEEEEEEEEEEEEEEEEEEEE+ DEEEEEEEEEf4(G(EEEEEEEEEEEEEEEEEEEE >EEEEEEEEEf4(2k5EEEEEEEEEEEEEEEEEE@ l8EEEEEEEEEi7 ({ (#BEEEEEEEEEEEEEEEEEq: 444444444)[;EEEEEEEEE$q>444444444444444444444444444444(+++444444444444444444-L8DEEEEEEEEEEEEEEEE(_;4444444444444444447777777773C8DEEEEEEEE%r@777777777777777777777777777777($ 666777777777777777777(g>EEEEEEEEEEEEEEEE1H9777777777777777777::::::::::::!CEEEEEEEE&sA::::::::::::::::::::::::::::::(g::::::::::::::::::9;:"BEEEEEEEEEEEEEEC:::::::::::::::::::::>>>>>>>>>>>>.c@EEEEEEEE'tB>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>(///>>>>>>>>>>>>>>>>>>9I?DEEEEEEEEEEEEE,gA>>>>>>>>>>>>>>>>>>>>> AAAAAAAAAAAA>FADEEEEEEE(uCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA( >>>AAAAAAAAAAAAAAAAAA3^BEEEEEEEEEEEED=IAAAAAAAAAAAAAAAAAAAAAA!!!DDDDDDDDDDDDDDD,pDEEEEEEE*vDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD(SDDDDDDDDDDDDDDDDDDDDD)wDEEEEEEEEEEE+tDDDDDDDDDDDDDDDDDDDDDDDDD###GGGGGGGGGGGGGGGCNFEEEEEEE+xEGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG(222GGGGGGGGGGGGGGGGGGDKG!EEEEEEEEEEEAPFGGGGGGGGGGGGGGGGGGGGGGGG$$$JJJJJJJJJJJJJJJJJJ3mGEEEEEE,yFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ(DDDJJJJJJJJJJJJJJJJJJ@ZIEEEEEEEEE1pGJJJJJJJJJJJJJJJJJJJJJJJJJJJ&&&NNNNNNNNNNNNNNNNNNLOM$FEEEEE-zHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN (@NNNNNNNNNNNNNNNNNNNNN5oIEEEEEEE"FLPMNNNNNNNNNNNNNNNNNNNNNNNNNNN(((QQQQQQQQQQQQQQQQQQQQQG]NEEEEE.{IQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ!!!(333QQQQQQQQQQQQQQQQQQPQP(GEEEEEEE_NQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ)))TTTTTTTTTTTTTTTTTTTTTTTT=lNEEEE/|JTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"""(JJJTTTTTTTTTTTTTTTTTTM[REEEED;oMTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++WWWWWWWWWWWWWWWWWWWWWWWWWWW6wLDEE0}KWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW###(0VVVWWWWWWWWWWWWWWWWWWCjPEEE3zLWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW---ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ4|MEE1~LZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%(x111ZZZZZZZZZZZZZZZZZZZZZ4|LE1LYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^]^]7|OD2M^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&&&(NNN^^^^^^^^^^^^^^^^^^[`]%%%wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwiii&]]]zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz222(LLLzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz___*,,,aaa}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~444( nnn~~~~~~~~~~~~~~~~~~~~~~~~}}}bbb...*...===@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===333@@@@@@@@@@@@@@@@@@???888%%%Z ?????????????????????????><<800 08<<>????????????????????????( WOZ3Pc9P!$_PiPrP+P]PjP6%P -P: PC6P{P\PQPPP`PPPpP)  P 7B /PQ'EE /P3 d/EEE /P  n4EEEE /P r6EEEEE 0PA  i2  p5EEEEEE 0Pd0Ey9  i2EEEEEEE 0P;EEEs7 [,EEEEEEEE0PO BEEEEf1 D"EEEEEEEEE1 P w9EEEEEEQ(  *DEEEEEEEEE1 P R)EEEEEEEE5   ?EEEEEEEEEE1 P^ +DEEEEEEEEB   m4EEEEEEEEEEE1 P  ?EEEEEEEEEEw8  B"EEEEEEEEEEEE1 P h2EEEEEEEEEEEEN'  BEEEEEEEEEEEE1 Pm A!EEEEEEEEEEEEED "  j3EEEEEEEEEEEEE2 P' CEEEEEEEEEEEEEEv8  3EEEEEEEEEEEEEE2 P z:EEEEEEEEEEEEEEEE?!  <EEEEEEEEEEEEEE2 P} W+EEEEEEEEEEEEEEEEE@   B"EEEEEEEEEEEEEEE2 P2 0EEEEEEEEEEEEEEEEEEEO(   ?EEEEEEEEEEEEEEE3 P @EEEEEEEEEEEEEEEEEEEB   C#EEEEEEEEEEEEEEEE3 P l4EEEEEEEEEEEEEEEEEEEEEP(  =EEEEEEEEEEEEEEEE3 P? E$EEEEEEEEEEEEEEEEEEEEEEA   5EEEEEEEEEEEEEEEEE3 P  #CEEEEEEEEEEEEEEEEEEEEEEEB#  o5EEEEEEEEEEEEEEEEE3 P };EEEEEEEEEEEEEEEEEEEEEEEE{;  EEEEEEEEEEEEEEEEEE3 PM \-EEEEEEEEEEEEEEEEEEEEEEEEEE(  M'EEEEEEEEEEEEEEEEEE3 P 5EEEEEEEEEEEEEEEEEEEEEEEEEEEZ-  |;EEEEEEEEEEEEEEEEEE4 P AEEEEEEEEEEEEEEEEEEEEEEEEEEE@ !EEEEEEEEEEEEEEEEEEE4 P[p6EEEEEEEEEEEEEEEEEEEEEEEEEEEEE,I&EEEEEEEEEEEEEEEEEEE4 P  J'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEV+ o6EEEEEEEEEEEEEEEEEEE5 P (DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE|; CEEEEEEEEEEEEEEEEEEE5 Pk=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+EEEEEEEEEEEEEEEEEEEE5 P%`0EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE9I&EEEEEEEEEEEEEEEEEEEE5 P : EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEV,c1EEEEEEEEEEEEEEEEEEEE6 Pz AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEq7 |<EEEEEEEEEEEEEEEEEEEE6 P0t8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@ CEEEEEEEEEEEEEEEEEEEE6 PO)EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEE6 P ,DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ .EEEEEEEEEEEEEEEEEEEEE6 P<>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE#EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEU- =#EEEEEEEEEEEEEEEEEEEEE8"Px c2EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJ( /EEEEEEEEEEEEEEEEEEEEE8"P=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=# !EEEEEEEEEEEEEEEEEEEEE9#P#-DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, CEEEEEEEEEEEEEEEEEEEE9#Pd N*EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE {<EEEEEEEEEEEEEEEEEEEE9#Pr8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@ d3EEEEEEEEEEEEEEEEEEEE9#P AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEq7 K*EEEEEEEEEEEEEEEEEEEE:#PQ :#EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEW. ******************'@/EEEEEEEEEEEEEEEEEEEE%G1************************************************************"""P****************************************))#h;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&J2************************************333333333333333333243DEEEEEEEEEEEEEEEEEEE,N8333333333333333333333333333333333333333333333333333333333333***P111333333333333333333333333333333333333333253BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED194333333333333333333333333333333333333555555555555555555545"x@EEEEEEEEEEEEEEEEEEE-P9555555555555555555555555555555555555555555555555555555555555+++P>5555555555555555555555555555555555555555550D7DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE B545555555555555555555555555555555555555777777777777777777777+^<EEEEEEEEEEEEEEEEEEE.Q:777777777777777777777777777777777777777777777777777777777777---P&&&777777777777777777777777777777777777777767+]<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE(g>7777777777777777777777777777777777777778888888888888888888884C9DEEEEEEEEEEEEEEEEEE0S<888888888888888888888888888888888888888888888888888888888888...P444888888888888888888888888888888888888888888$wAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1K;888888888888888888888888888888888888888 ::::::::::::::::::::::9:!CEEEEEEEEEEEEEEEEEE1S=::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::000P/::::::::::::::::::::::::::::::::::::::::::7@;CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEC:::::::::::::::::::::::::::::::::::::::::: ;;;;;;;;;;;;;;;;;;;;;;;;,c?EEEEEEEEEEEEEEEEEE2U>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;000Pv%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3R=DEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)k@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;!!!========================9E>DEEEEEEEEEEEEEEEEE3V?============================================================222P666========================================<=+kAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE7L>=========================================="""?????????????????????????>>&yCEEEEEEEEEEEEEEEEE4W@????????????????????????????????????????????????????????????444P!>>>???????????????????????????????????????=@?"CEEEEEEEEEEEEEEEEEEEEEEEEEEE"C?>???????????????????????????????????????????### @@@@@@@@@@@@@@@@@@@@@@@@@@@6WAEEEEEEEEEEEEEEEEE5XA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@555Pb###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;K@DEEEEEEEEEEEEEEEEEEEEEEEEEE2_A@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$$$!!!BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB!DEEEEEEEEEEEEEEEE6YCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB666P777BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3`BEEEEEEEEEEEEEEEEEEEEEEEEEDACBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB%%%!!!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4aCEEEEEEEEEEEEEEEE7ZCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC777P BBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)wDEEEEEEEEEEEEEEEEEEEEEEEE0hCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC&&&"""EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDFE EEEEEEEEEEEEEEEE9[EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE999PN EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEBIE EEEEEEEEEEEEEEEEEEEEEEEECHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&&&###GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG6bEEEEEEEEEEEEEEEE:\FGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG:::P666GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\HEEEEEEEEEEEEEE<_HJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ===P<JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJIJJ&FEEEEEEEEEEEEEEEEEEE:cHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ)))%%%KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK+{GEEEEEEEEEEEEE=`IKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK>>>P444KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKFSJEEEEEEEEEEEEEEEEEE'FKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK***&&&MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMHSLEEEEEEEEEEEEE>aJMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM???PGGGMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM>>eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee888000ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggUUUPZZZggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg666(((hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhVVVPggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh---kkkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjWWWP\888jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjhhhkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkXXXPXXXkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkPPPmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmZZZPjjjmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmUUUYS***ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo[[[PI111ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo000hhhpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\\\PUUUpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppkkk)555rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr^^^P lllrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr;;;5bbbsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss___P8+++sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssfffsssuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu```PPPPuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuttt S///wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwbbbP lllwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww666a999xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcccP)###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx???111xxxzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzdddPnIIIzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzyyy666iii{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{eeePkkk{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{lllT:::ttt}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}gggP|||}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}vvv===]000]]]|||iiiPZBBB|||___222*111<<<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@555P===@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@<<<111/S'i|6 ??  ??( NT <Dp'+)6)y *38c w @ O ^x&^9 om)' 6|2(q ,?Dz L!<Vk[k%z0<  J d0]- <F[, 2CEE[,YK%EEEE[,a/FEEEE[, r6FEEEEE[,h ~;EEEEEEE[,$ ?EEEEEEEE[, @EEEEEEEEE[,w BEEEEEEEEEE[,.O'1 BEEEEEEEEEEE[, *EE / BEEEEEEEEEEEE[,  @EED / @EEEEEEEEEEEEE[,:h2EEEED )  >EEEEEEEEEEEEEE[, ? FEEEEEC ! };EEEEEEEEEEEEEEE[, DEEEEEEEA  p6EEEEEEEEEEEEEEEE[,H {;EEEEEEEEE=   _.FEEEEEEEEEEEEEEEE\-  V*EEEEEEEEEEEu8  H$FEEEEEEEEEEEEEEEEE\-  .FEEEEEEEEEEEEb/   /EEEEEEEEEEEEEEEEEEE\- V  AEEEEEEEEEEEEEFH$   CEEEEEEEEEEEEEEEEEEE\-  l4EEEEEEEEEEEEEEEE ,  };EEEEEEEEEEEEEEEEEEEE\-  C"FEEEEEEEEEEEEEEEEA   a/EEEEEEEEEEEEEEEEEEEEE\- f  DEEEEEEEEEEEEEEEEEEv8   :FEEEEEEEEEEEEEEEEEEEEE\-  " ~;EEEEEEEEEEEEEEEEEEEFU*   CEEEEEEEEEEEEEEEEEEEEEE\-    Z,EEEEEEEEEEEEEEEEEEEEEF.  x9EEEEEEEEEEEEEEEEEEEEEEE\-  u 3FEEEEEEEEEEEEEEEEEEEEEE@    N'FEEEEEEEEEEEEEEEEEEEEEEE\-  , AEEEEEEEEEEEEEEEEEEEEEEEEh2   "EEEEEEEEEEEEEEEEEEEEEEEEE\-    p6EEEEEEEEEEEEEEEEEEEEEEEEEF8   |;EEEEEEEEEEEEEEEEEEEEEEEEE\-    H$FEEEEEEEEEEEEEEEEEEEEEEEEEEA    J%FEEEEEEEEEEEEEEEEEEEEEEEEE\-  8 #DEEEEEEEEEEEEEEEEEEEEEEEEEEEEe1   DEEEEEEEEEEEEEEEEEEEEEEEEEE\-    =EEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/   n5EEEEEEEEEEEEEEEEEEEEEEEEEEE].    _/EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE>  3FEEEEEEEEEEEEEEEEEEEEEEEEEEE].  E 6FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEN'  >EEEEEEEEEEEEEEEEEEEEEEEEEEEE].   BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEC   J&EEEEEEEEEEEEEEEEEEEEEEEEEEEEE].   s7EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe2   BEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  T M'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%   X,EEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].   &EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEr7   DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].   >EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF.  _/EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. d c0EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEx9  DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. ! ;FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF0  ].EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEw9  DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. s v9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF+  T*EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. + Q)FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEo5  AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  *EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE   B#FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  @EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_/  =EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. 5 g2EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEC   ,FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].   ?"FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFF%  h3EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=  DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. C z:EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF)  D$FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  U+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa0  y:EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE].  .EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEB   EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE]. R @EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7   N)EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/   k4EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEk4   }<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/    C$FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEC  EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  a  !DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7   J'FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  }<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEf2   v9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/    Y-EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEA DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  p  2FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF*7FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  )AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEES*  `/EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/   o6EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEz:  =EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/    H&FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  4$DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF29 FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  =EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEU,  [.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/   ^/EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEw9  z;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  A 6FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEBBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE^/  BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF%&FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  r7EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF@#?#FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  O  L(FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\/ Z.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  (EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEu9  r8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  >EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  _  b1EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  :!FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF+$FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF=#5FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 n u9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEQ+F&FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 'P*EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEc1V-EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEs8 e3EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 | ?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE< s8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 2e3EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEA }<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 ?#EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEC?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0  CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 > y:EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 T,EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF&DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 /EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF-EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 @EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF1EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 i5EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF6  EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_0 C%FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF6 $FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 #DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7!$FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 {;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7! EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 X.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7!EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 3EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7!EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF0DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 ,EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF-CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 Q+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF'AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 `v9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE#?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE|<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 <#FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEECr8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 M b2EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@e3EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 >EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE~=V-EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 *DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEr8E'FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE`1 ; L)FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEb25!FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 q8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEP+&EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF=$CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 , 7"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF,?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 r]0EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDp8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 ~=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@Y/EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 'DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEt9?%FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2 ^G(EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEZ/(EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2m6EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF@%BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'x:EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEa2K 3!EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEB !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! `5EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe7! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! _6EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEx413333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333!!! 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333323 AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'c<3233333333333333333333333333333333333333333333333333333333333333333333333333332223333333333333333333333333333333333333331;4EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%l>413333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333!!!84443333333333333333333333333333333333333333333333333333333333333333333333333333333333330>5DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.I7333333333333333333333333333333333333333333333333333333333333333333333333333333333444444444444444444444444444444444444444423 BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%m>423444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444!!!+++444444444444444444444444444444444444444444444444444444444444444444444444444444444444433+U:EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED374444444444444444444444444444444444444444444444444444444444444444444444444444444333555555555555555555555555555555555555555534&j=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&m>534555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555""" 444555555555555555555555555555555555555555555555555555555555555555555555555555555555555534$r?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE!~A524555555555555555555555555555555555555555555555555555555555555555555555555555555444666666666666666666666666666666666666666666/N9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&n?645666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666###)777666666666666666666666666666666666666666666666666666666666666666666666666666666666666596CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)b=6566666666666666666666666666666666666666666666666666666666666666666666666666666665557777777777777777777777777777777777777777776:7DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&n?756777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777###p)))7777777777777777777777777777777777777777777777777777777777777777777777777777777777777671I:EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1G9777777777777777777777777777777777777777777777777777777777777777777777777777777777666777777777777777777777777777777777777777777857#{AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&n?867777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777###555777777777777777777777777777777777777777777777777777777777777777777777777777777777777767*c>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEC777777777777777777777777777777777777777777777777777777777777777777777777777777777888777888888888888888888888888888888888888888888878-\=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'o@978888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888$$$999888888888888888888888888888888888888888888888888888888888888888888888888888888888888878"}BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&p@8688888888888888888888888888888888888888888888888888888888888888888888888888888889997779999999999999999999999999999999999999999999996B:DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'o@979999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999%%%['''9999999999999999999999999999999999999999999999999999999999999999999999999999999999999996@:DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1Q<989999999999999999999999999999999999999999999999999999999999999999999999999999999999888::::::::::::::::::::::::::::::::::::::::::::::79!CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE(o@:8::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::&&&666:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::9:0U=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED9<:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::999;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;-a?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE(pA;9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9;(p@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&tA;9:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8D<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE(pA<:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&H$$$<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=; CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE3R>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<=:<#~BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)pA=;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'''444<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<7K>DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<===;;;=================================================<=1[@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)qB=;============================================================================================================================((( ========================================================================================;=.b@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*nA=;========================================================================================<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)qB><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>(((6 ???>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>%{CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE8L?>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>===????????????????????????????????????????????????????=>)rBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*qB?=????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????)))333>>>?????????????????????????????????????????????????????????????????????????????????>??>>??????????????????????????????????????????????????????9N@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*qB@>????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????))) >>>???????????????????????????????????????????????????????????????????????????????????????6VAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE2^B??????????????????????????????????????????????????????????????????????????????????????????@@@>>>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A>@#DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*rC@>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@***(AAA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>@,nBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED?B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@A4\BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+rCA?AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA***m111AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,nCA@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@@@BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBABBDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+rDB@BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB+++???BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB>>DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBGDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE&}DDBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEECCCEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEBJEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,tEECEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE---FFFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE;WEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=TEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF/nEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,tEGDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF---E)))FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF0mEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'~EFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEEEGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGDKFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-tEHEGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG...>>>GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGFFG$EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE>UFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGEEEGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHFG2lFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-tEHFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG... HHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGCPGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE){FHFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGJHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-uFIGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH///4%%%IIIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIGH9bGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEBRGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIII GGGIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHI8dGEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.uFJGIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII///};;;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIGI,yFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/sFJGIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII HHHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJIJ$FEEEEEEEEEEEEEEEEEEEEEEEEEEEE.vGKHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ000 IIIJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHLI!EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGMIJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ IIIKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKJK@ZIEEEEEEEEEEEEEEEEEEEEEEEEEEEE.vGLIKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK000&!!!KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKJKAXIEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE8hHKJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK IIIKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLJK-zGEEEEEEEEEEEEEEEEEEEEEEEEEEE.vGLJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK111k888KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLJK5mHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE$FKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLL JJJLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLIPLEEEEEEEEEEEEEEEEEEEEEEEEEEE/wGMKLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL111HHHLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMKL'FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEECZKLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMM KKKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLM:gJEEEEEEEEEEEEEEEEEEEEEEEEEE/wHNKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM222NNNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMISLEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1uHNKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM LLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMN(GEEEEEEEEEEEEEEEEEEEEEEEEE0wHOLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN222V444NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMN>cKEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE!FLPMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN MMMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOIVMEEEEEEEEEEEEEEEEEEEEEEEEE0xIPMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO333HHHOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPMO0xIEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEB`LONOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO NNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPNO;jKDEEEEEEEEEEEEEEEEEEEEEEE0xIPNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO444PPPOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONPO#FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1wIPNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPP OOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQOP+HEEEEEEEEEEEEEEEEEEEEEEE0xIQOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP444D///QQQPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPH[NEEEEEEEEEEEEEEEEEEEEEEEEEEEEE#FORPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQ OOOQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQNUPFEEEEEEEEEEEEEEEEEEEEEE1yJRPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ555FFFQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRPQ:mLDEEEEEEEEEEEEEEEEEEEEEEEEEEEG]NQPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ PPPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQRDbNDEEEEEEEEEEEEEEEEEEEEE1yJSQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR555 RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQR+HEEEEEEEEEEEEEEEEEEEEEEEEED9nLRQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR QQQSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTQS5tKDEEEEEEEEEEEEEEEEEEEE2yJTRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS6662***TTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSOVR EEEEEEEEEEEEEEEEEEEEEEEED,ISRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS QQQSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTST)HEEEEEEEEEEEEEEEEEEEE2yJTRTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS666{CCCSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSEdPDEEEEEEEEEEEEEEEEEEEEEE"FQVSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTT RRRTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTPXS FEEEEEEEEEEEEEEEEEEE2zKUSUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT777 RRRTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUST5vKDEEEEEEEEEEEEEEEEEEEEEJ_QTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUU SSSUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUJ`REEEEEEEEEEEEEEEEEEE3zKVTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU777%$$$VVVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUT&GEEEEEEEEEEEEEEEEEEEDAjOUTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU TTTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUVBkPEEEEEEEEEEEEEEEEEE3zLWUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV888g???VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVN^SEEEEEEEEEEEEEEEEEED7vLVTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV TTTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVXUW9uNDEEEEEEEEEEEEEEEE3zLWUWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV888 RRRVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWVV@mPDEEEEEEEEEEEEEEED/KWVWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWWW UUUWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXVX1}KDEEEEEEEEEEEEEEE3{LXVXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW999YYYWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXVX/KDEEEEEEEEEEEEEE(HVXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXX VVVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+IDEEEEEEEEEEEEEE4{LYWYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX999T:::YYYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXVZW!GEEEEEEEEEEEEE#GU[WXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYY WWWYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYWZX'HDEEEEEEEEEEEEE4|MZXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY:::QQQYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYXYKfTEEEEEEEEEEEE!FS^WYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY XXXZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZV]X%GEEEEEEEEEEEEE4|M[YZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ:::ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[YZ:wODEEEEEEEEEFQbWZYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ YYY[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Z[V_Y#GEEEEEEEEEEEE5|M\Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[;;;A333\\\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Z[)IEEEEEEEEFPdW[Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ YYY[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[V`Z#GEEEEEEEEEEE5|M\Z\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[;;;NNN[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[UaYFEEEEEEEOgW\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\ ZZZ\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\WaZ$HEEEEEEEEEE5}N][]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\<<< \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]\\FnTDEEEEEOhX]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]]] [[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]XaZ%HDEEEEEEEE6}N^\]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]<<<0...^^^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^\]3MDEEFRfY]\]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] \\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Z`\(IDEEEEEEE6~O_]^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^===yKKK^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\_]$HE!GUdZ^]^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ]]]_______________________________________________________________________________________________________________________________________]`^-LDEEEEEE6~O`^____________________________________________________________________________________________________________________________===\\\________________________________________________________________________________________^_RiY&IYc\_^____________________________________________________________________________________________________________________________________________________________________________ ]]]_____________________________________________________________________________________________________________________________________________4NDEEEEE6~O`^`___________________________________________________________________________________________________________________________>>>#(((aaa_______________________________________________________________________________________`___________________________________________________________________________________________________________________________________________________________________________________``` ^^^`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````a_`>yRDEEEE7~Oa_a```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````>>>fEEEaaa````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````aaa ___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab`aIrWEEEE7Pb`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa??? \\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ___bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbabUj\"HDE8Pcabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb??? cccbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ```cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccbc^fa-LD8Qdbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc@@@Q@@@dddccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc aaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccdcd>}S8Qebdccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc@@@ZZZccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddd bbbdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddedd_hbedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddAAAeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeee bbbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeAAA?999fffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee cccfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffBBBWWWfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff bbbgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggCCCfffgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggfff ]]]gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggCCC.222iiiggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggeeeWWWhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhDDDwRRRhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh___JJJiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiDDDfffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiUUU888kkkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjEEE!+++llljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjEEEg$$$mmmkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkFFFbLLLkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklll0007lllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkFFF eeekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkknnnQ ```llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllFFF###nnnlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllgggCCCmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmGGGOFFFnnnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmPPPrqqqnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnGGGcccnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnppp***$gggoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooHHHpppoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooolll <???pppooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooHHH<===qqqoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooLLLgqqqppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppIII___ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppsssOOOqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqIIIpppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq[[[ sssrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrJJJ-666tttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrttt!!!KKKsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssKKKtYYYsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssXXX0 pppssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssKKKpppsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssttt222vvvtttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttKKK ...vvvtttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttvvv??? `XXXuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuLLL`SSSvvvuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuubbb{ nnnvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvLLL nnnvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvsssvvvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwMMM%%%yyywwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxx(((,K---yyywwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwMMMLKKKxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwyyy999e|666zzzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxNNNkkkxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx{{{AAA666{{{yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNNN zzzyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy{{{AAA...zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzOOO:BBB{{{zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{999 sss{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{PPPggg{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{www''' ]]]}}}{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{PPPzzz{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}eee |666xxx}}}||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||QQQ+:::~~~|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}}}{{{???L SSS~~~}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}QQQr```}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}ZZZ_YYY~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~RRRzzz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~___'`HHHvvvSSS111xxxNNNq%%%OOOqqqSSS]YYYtttSSS(((+++DDDZZZjjjtttzzz}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}RRR ttt}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}{{{tttkkk]]]GGG...&hr$qJz, 7fk=??~~|xxp`@@@``pxx|~~??( %Fm?uO*MDxX) FC3SRC b:CL fC?|" C4!C4CL.oCICfCZ/UCwC$7CeVfC'CCu.&C3C1CS:Cb:C>c:C a.CRCHDC-CCY\C.CW Cf#C$FCwCs0C16CdC\C;C ,sCCG2sCC2jCTC LCCb "C$NvCCp0C/aCC&C8TcC CCD+.CZ]CCSCC-%CaUGC|gCCmC,CC~C9C CCBCCCQCCC^C CCkC*CCyC7C CCAD" C g1H %C &=IE #CN@ EGFE #C \-HFEFE #C u7IEEEFE #C] *@HEEEEFE #C @!EGEEEEEFE #CT)HFEEEEEEFE #Ci f1IFEEEEEEEFE #C) w9IEEEEEEEEEFE #C ">IEEEEEEEEEEFE #Cx .BHEEEEEEEEEEEFE #C49EGEEEEEEEEEEEEFE #C D"GFEEEEEEEEEEEEEFE #CN&HFEEEEEEEEEEEEEEFE #C>W+HFEEEEEEEEEEEEEEEFE #CZ,IEEEEEEEEEEEEEEEEEFE #C d0HEEEEEEEEEEEEEEEEEEFE $CK g2IEEEEEEEEEEEEEEEEEEEFE $CU* # g2IEEEEEEEEEEEEEEEEEEEEFE $CB"K>  g2IEEEEEEEEEEEEEEEEEEEEEFE $CZ "CFH?  g2IEEEEEEEEEEEEEEEEEEEEEEFE $C y9HEEH>  g1IEEEEEEEEEEEEEEEEEEEEEEEFE $CX+IEEEEH> `.IEEEEEEEEEEEEEEEEEEEEEEEEFE $Cg3FFEEEEEH? [,HEEEEEEEEEEEEEEEEEEEEEEEEEFE $C' ?GEEEEEEEH< T)IEEEEEEEEEEEEEEEEEEEEEEEEEEFE $Ck3HEEEEEEEEEH{:  M&HEEEEEEEEEEEEEEEEEEEEEEEEEEEFE $CuG$HEEEEEEEEEEEIs7 B!GFEEEEEEEEEEEEEEEEEEEEEEEEEEEFE $C5 %DFEEEEEEEEEEEEIl47FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE $C z;HEEEEEEEEEEEEEEI`. +DGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE $C[,IEEEEEEEEEEEEEEEEHU) AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE $C=7GFEEEEEEEEEEEEEEEEEGE#  =HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C  AGEEEEEEEEEEEEEEEEEEFF7   s7IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C  m4HEEEEEEEEEEEEEEEEEEEEGD (   c0HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % CI K%HEEEEEEEEEEEEEEEEEEEEEEG?    O'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C  )EFEEEEEEEEEEEEEEEEEEEEEEEHx9    :GFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C   ~<HEEEEEEEEEEEEEEEEEEEEEEEEEHf1     &CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % CX ].IEEEEEEEEEEEEEEEEEEEEEEEEEEEHO(   =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C ;HFEEEEEEEEEEEEEEEEEEEEEEEEEEEFG9   o5IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C  AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGB #   U*IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % Cg   p6HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH}<    :GFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C$ M'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHf1     !CGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C -EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHJ%    z:HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % Cs   =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE,   _/IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C0  a/IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG>    =HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE % C = GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEIj3     !CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C  BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHK&    v8HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C;  t7HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE*   V+IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C  R)HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH~<    0FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C 0FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH^.    >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  CI  ?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG8   a/IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C  e1IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG?    ;GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C B"HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHg2    @GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  CV  "CGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH=   f1IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C  w9HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGA    ;HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C V+IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHg2    ?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  Cc 3FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH<   `/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C$  ?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF?    1FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  C  i3HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH_/     };GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE&  Co F$HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF0   R)IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C/ %DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG|;     #DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  z:HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHM'    l5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C Z-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFC    :GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C; 8GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHg2   >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C   @GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG4   P)IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  l5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG{;    BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  CC J&IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHI%    c1HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C (DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGA    +FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C   |;GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEIY-    p6HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  CS ].HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFD#   8GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C :GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHf2   z;HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF,   A"HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  Cc o5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHp6   =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C" L'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG3   I%HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  ,EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHw9  ?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  Cp  <GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG9    J&HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C-  `/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGw9  ?FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C >!GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH9    K&HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C~  BGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGw9  >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C9 r7HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG9    D$HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  Q)HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHt8  =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  .EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG3    >!HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  CD  >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHn5   w9GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  d1IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+    5GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C @"GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHc1   m5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  CQ  !BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFC!    )EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C v9HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHV,    ^/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE'  C  T+IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF@  BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C`  2FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHF%    L(IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C  >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGy:  =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C h3HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG3    7GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  Cl  E$HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHf2   l4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C+   %CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFC    #DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C w9HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHO)    R*HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C{  X-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG~<   =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C7   6FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF3    4GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C   ?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHd2    e2HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C j4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFB  BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  CC   I&HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHE%    B#HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C  (DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGr7  p7HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  C {;HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFD%   "DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE(  CO   Z-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHN(     M(HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C  : GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG{;   v9GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*   %EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C^   m5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHS*     L(HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C   K'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGz;    u9HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C  ,EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*   %DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) Ck ~<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHS+     K'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C(    ^/IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGx:     q7HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE) C  GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHL(  <"GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* C f2HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGl5  Y-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* Ch D%GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF?  v9GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* C'  %CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE+  AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* C v9HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHE%  2GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* Cu V,HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHc1  N(HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* C4  5FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGy: i4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* C  ?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFC  }<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE* C h4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF5  !CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C?  H'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHO)  7 GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C  (CGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHg3  P)HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C y:GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG}< g3HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ CJ Z.HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFB {;GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C  9 GFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF3  BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C @GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHF&  /EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ CY l5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH[.  A$HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C  J(HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGq7  U,HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C +DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF> i4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ Cg |<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFB# {;GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C&  ]/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF1  @FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ C :!GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGC$  (DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ Ct AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHV-  5GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C2 o7HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHh4  G'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C N*HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGu9 X-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C -DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG> h4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C==GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFC  t8GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C  a1HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+ =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C ?#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF9! AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, CH !AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHF&  #EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C r8HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHT,  0FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C Q+HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH_0  <"GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, CV 1EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGj4 H'HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C  >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGu9 R+HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C c2HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG= \/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, Cc B%GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFA e3HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C#  $BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFBm6HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, Ct9GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFD( u9GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, Cp T,HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE/ |<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, C/ 5 FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF6  >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, > >GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF;" AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, 2s f3HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHB% BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,  E&GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHE& $CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,   (CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHM) #CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, w:GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHT,  *DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,  W-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHS,  1EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,   8!FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH[/  0EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, @GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa1  0EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, i5HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH`1  0EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,   I(HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH`1  9!GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,  *DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH`1  =#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-{<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa1 <#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- [/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa1 <#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- :#FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa1 =#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- @FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa1 6!FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- m6HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa10EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- L*HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa11EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- -DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa11EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- |<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHa11EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE- _1HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHX. (CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-B%GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHR, %CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-K l5IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHS, $CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-6,&BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHK) AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-C} @%GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHF' AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-C a1HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG@% =GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C*=GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF<# {<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.Ci /EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE5!s8GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C O+GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFE/l6HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C n7GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFC&c3HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.CW"AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFB  [/HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C =$FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF@ Q+GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C \0HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG}< G'GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.CE|<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGs9<#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C,CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHh4/FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C  K)HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH]0 %DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C5k6HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHQ, @FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.Cz?GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGD' }=GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C  8"FFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF7"r8GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.C* X.HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE) e3GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/Chw:GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFB U-GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C)CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG~=E'GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C  F(GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGs95!FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/CTf4HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHd3)CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C>GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGR-@FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C 3 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG@&y:GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/CDT-HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/e4GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/Cr8HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFA#Q,HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C %BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG>>%GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C4@&FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGn7-EFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/Cya2HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHY/AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C ~=HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHD' w;GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/C&0DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1 b2HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/Cc O+GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFAN+GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ Co7HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGx;5"FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ C#AGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHb2$BEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ CS=%FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGK*y;GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ C\0HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF3!d3GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ C z<GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFB!I*GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ CB-CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGv:0EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/ C I)FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG^1***...----------------------------------------------------------------------------+-,4/CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)B2.),---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------/// C ///----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+,-*,#s>FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF'P5.',--------------------------------------------------------------------------------------------------------------------------------------------------------- 000555444444444444444444444444444444444444444444444444444444444444444444444444444444413"y@FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.G7503444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444666 C4'''6663334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444031:4CFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED/C6403444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 0004443333333333333333333333333333333333333333333333333333333333333333333333333333334.2(c<FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.F74/2333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333555 Ct1114443333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334-2-M8EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF B354323333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 0004443333333333333333333333333333333333333333333333333333333333333333333333333333334.2-O8FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.F74/2333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333555 C6663333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334-2'f=FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF%p?4.2333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 1115554444444444444444444444444444444444444444444444444444444444444444444444444444444242=5DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/G7513444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444666 C$$$$777444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444424444!}AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF*Z;5.3444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 111555444444444444444444444444444444444444444444444444444444444444444444444444444444434424"{AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/G7513444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444666 Cb0005554444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444445030B6DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/F7503444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 1115554444444444444444444444444444444444444444444444444444444444444444444444444444444446/3(e=FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/G7513444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444666 C6665554444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444546.3+Y;FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE B465534444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555444 111666555555555555555555555555555555555555555555555555555555555555555555555555555555555614.M9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE0H8624555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555777C!!!888555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555545614%q?FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF%p?614555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666555 1116665555555555555555555555555555555555555555555555555555555555555555555555555555555556353<6CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE0H8624555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555777CP...7775555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555353;6 BFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF+X;604555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666555 222777666666666666666666666666666666666666666666666666666666666666666666666666666666666666725$xAFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1I9735666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666888C7776666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667150L9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE2C8736666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666777666 222777666666666666666666666666666666666666666666666666666666666666666666666666666666666666715+_<FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1I9735666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666888C:::666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666715)c=FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF!B666656666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666777666 3338887777777777777777777777777777777777777777777777777777777777777777777777777777777777778462H9EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1J:846777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777999C@,,,999777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777757767#{AFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF(h>816777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777888777 333888777777777777777777777777777777777777777777777777777777777777777777777777777777777777767787 CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1J:846777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777999C 6668887777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777778374B9DFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF/P;836777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777888777 333888777777777777777777777777777777777777777777777777777777777777777777777777777777777777777936(m?FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1J:846777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777999C:::777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777826.W<FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED5=8867777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777888777 4449998888888888888888888888888888888888888888888888888888888888888888888888888888888888888889370S<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE2K;958888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888:::C0)));;;888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888947'n@FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF&t@9488888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888889998884449998888888888888888888888888888888888888888888888888888888888888888888888888888888888888889686>9DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE2K;958888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888:::Cq555:::8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888687;8!CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF.Y=937888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888999888555:::999999999999999999999999999999999999999999999999999999999999999999999999999999999999999889:58&tAFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE3K;:69999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;;;C;;;999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999:483K;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED5C:968999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999:::999555:::999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;48.[>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE3K;:69999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999<<<C$'''<<<999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;38,a>FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF${B:79989999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999:::999555:::999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999:796B;DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE3K;:69999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999<<<C_444;;;999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999989:79%yBFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF-_>;48999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999:::999666;;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::9:;79%yBFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE4L<;7::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::===C<<<;;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;7:7C;DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE5H;;7:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;;;:::666;;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::<59.^>FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE4L<;7::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::===C###>>>::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::<491U=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF#~B;9::9:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;;;:::777<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<8;7F<EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE5M=<8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>CP333===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;<6;*l@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-c?=6:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<;;;777<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<8;%xBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE5M=<8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>C<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<9;;<;"CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED7G<<9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<;;;777<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=6:0\?FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE5M=<8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>C ???;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=7;6K=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE$|B<8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<;;;888===<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<=:<9E=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE6N>=9<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<7;/_@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF/_?>7<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<===<<<888===<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>8<'uBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE6N>=9<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>===================================================================================================>8<3W?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE6O?>:==========================================================================================================================================================================================================================================================@@@C@@@===============================================================================================================================================================================:=;C= DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'vB>9<=<=========================================================================================================================================================================>>>===999>>>===================================================================================================>;= DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE6O?>:==========================================================================================================================================================================================================================================================@@@C/---@@@==============================================================================================================================================================================?8=4T?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE2Y@?9============================================================================================================================================================================>>>===999>>>======================================================================================================?9=*mAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE6O?>:==========================================================================================================================================================================================================================================================@@@Cp :::???==============================================================================================================================================================================?8=,jAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE D><============================================================================================================================================================================>>>===:::???>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>?;>7P?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE7O@?;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>AAACAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=>>>>$CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+mB@9>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>???>>>:::???>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=>>=>$CEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE7O@?;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>AAAC ***BBB>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>?:>9J?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE7O??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>???>>>;;;@@@??????????????????????????????????????????????????????????????????????????????????????????????????????>??A9>1`AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE8P@@>>????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????>??A9>2^AEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%~D?=??>???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????@@@???;;;@@@?????????????????????????????????????????????????????????????????????????????????????????????????????????@=?=E?EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE8P@@@%~DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE9QAA=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CCCCAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B;@/hBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE9OAA=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AAA@@@<<AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDDC:444DDDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB>A=JADEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE5[BC=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBAAA===BBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDDC @@@CCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD>>CCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBC@B>KBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:RCC?BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBEEECFFFBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD>B+qDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1eDD=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCBBB>>>CCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD>B+sDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:RCC?BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBEEEC-000EEEBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBC@BAEB#DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE E?GBC@BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCBBB???DDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD?C;RCEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE;SDD@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCFFFCn ???DDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD>C;SCEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.mDE>CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDCCC???DDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD@C)zDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE;SDD@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCFFFCFFFCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCE>C2fDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE>MCDACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDCCC???DDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCE?C:WDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE;SDD@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCFFFC ---GGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCDAC({DEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE,sDE?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDCCC???EEEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEBD'~EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEREEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=UEGBEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFEEEAAAGGGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHBF9^FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=VFHCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFIIIC $$$JJJFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFIAF5dFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE*yEGCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGGGFFFAAAGGGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFEF%EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=VFHCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFIIIC8777IIIFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHCF*yEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE=UFHCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGGGFFFBBBHHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGIBG9_FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE>VFIDGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJJJC EEEHHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHDGCLG!EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+yEHCGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHGGGBBBHHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGFGHFG'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE>VFIDGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJJJC KKKGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGICGVFIDGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJJJC+444KKKGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJCG1nFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE-uFICGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHGGGCCCIIIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIFH)|FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE?WGJEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHKKKCk DDDJJJHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIGHHHH'FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEBRHIFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIIIHHHCCCIIIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHJEH?WGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE?WGJEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHKKKCKKKIIIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHJEHBRGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE1pFJDHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIIIHHHDDDJJJIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIKEI-vGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@XHKFIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIILLLC000MMMHHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIKDI9dHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE FFNHJGIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJJJIIIDDDJJJIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIKGICRHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@XHKFIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIILLLCXAAAKKKIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIKFI-wFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE6iGLEIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJJJIIIDDDJJJIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIKEI3mGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@XHKFIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIILLLCKKKJJJIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJGIGMI#FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%FIJIJHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJJJIIIEEEKKKJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJKIJHMJ"FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@YILGJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJMMMC+++OOOJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJLFJ?[IEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE<`IMFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJKKKJJJEEEKKKJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJMEJ:cHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@YILGJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJMMMCG>>>MMMJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJMEJ5lHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)}FKHJJIJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJKKKJJJFFFLLLKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKJKKIK(GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAZJMHKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKNNNCKKKKKKJJJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKJKKIK)GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEECWJLHKJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLLKKKFFFLLLKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKNHKAZJEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAZJMHKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKNNNC '''OOOKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKMHKFSJ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE2rHNGKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLLKKKFFFLLLKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKMGK1tHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAZJMHKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKNNNC9;;;OOOKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKNGK;cIEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"FHOJLIKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLLKKKGGGMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMJLIQK"FEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEB[JNILLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLOOOC|JJJMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNIL0uHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE>>UUUQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQROQNUP#GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED;mLTMRQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRQQQLLLSSSQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQTMR>iMEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF_OSOQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQUUUCwNNNSSSQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQTNRCaNEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED,~HROQRPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRQQQLLLSSSQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRQQTNR0zJDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEF_OSOQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQUUUC"""UUURRRQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRQQTMR7rKDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED"GLXPSORQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRQQQMMMTTTRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSQRPUQ%GDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG_OTPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRVVVC':::WWWRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSQRRRR*HDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDBeNUOSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSRRRMMMTTTRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUNSF`OEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEG_OTPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRVVVCe LLLTTTRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRTPSK[PEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED5tKUNSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSRRRMMMUUUSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSVOT;oMDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH`PUQTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSWWWCVVVSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSVOS?jNDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED*ISSSTRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTSSSMMMUUUSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTRSTQT/|JDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH`PUQTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSWWWC555XXXSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRSUPT1zJDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED!FMZRUQTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTSSSMMMUUUSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSUQTQVS%GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEH`PUQTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSWWWCTIIIVVVSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSUQSQVS%GDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDfOVOTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTSSSNNNVVVTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTWQUI`QEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEIaQVRUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTXXXCVVVUUUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTWQUGbQEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED9sMWPUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUUTTTNNNVVVTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTWPU@jNDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEIaQVRUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTXXXC000YYYTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTWPU:qMDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED.JUSTUSTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUUTTTOOOWWWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUWRV6vLDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJbRWSVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYYCCFFFXXXUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUUSU,IDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED%HRXTVSUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVVUUUOOOWWWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVTUVTU,JDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJbRWSVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYYCTTTVVVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUWSUO[S!FDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEDFK`RXRVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVVUUUOOOWWWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUWSVQYT%HDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJbRWSVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYYC )))ZZZUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXRVChPDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEECiPYQVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVVUUUPPPXXXVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYSWLaSFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJbSXTWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVZZZC4BBB[[[VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYSW5yLDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED;rNYRWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWWWVVVPPPXXXVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYRWDiQEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJbSXTWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVZZZCvSSSXXXVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWUVUWU'HDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED2{KXTVVUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWWWVVVPPPXXXVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWVVZSX=qODEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEJbSXTWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVZZZC$$$[[[WWWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWVYTWKbSFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED+JVWWXUWVWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWWWVVVQQQYYYWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXVWYTX5yMDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEKcSYUXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW[[[C%===\\\WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWZSX=pODEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED%HS\VYUXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXXWWWQQQYYYWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXVXXVX/KDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEKcSYUXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW[[[Ce PPPZZZWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXWWYVX/KDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED FNaTZUXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXXWWWRRRZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYWXVZW*IDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEELdTZVYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\\C[[[YYYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXZVYS]V#GDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEIgS[UYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYXXXRRRZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXZUYS]V$HDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEELdTZVYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\\C777]]]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\TYGiREEEEEEEEEEEEEEEEEEEEEEEEEEEEEEClQ\TYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYXXXSSS[[[YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\VZPbU!FDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEMeU[WZYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]]]CRNNN\\\YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]UZ9xNDEEEEEEEEEEEEEEEEEEEEEEEEEED?rP\UZYXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZYYYSSS[[[YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\VZLeTEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEMeU[WZYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]]]C[[[ZZZYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZXYXZY)IDEEEEEEEEEEEEEEEEEEEEEEEED:vO\VZYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZYYYSSS[[[YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]VZIiTEDEEEEEEEEEEEEEEEEEEEEEEEEEEEEMeU[WZYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]]]C111^^^YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\WZOcVFEEEEEEEEEEEEEEEEEEEEEEED6zM\WZZXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZYYYTTT\\\ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^W[EnSEDEEEEEEEEEEEEEEEEEEEEEEEEEEEMeV\X[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^^^C@JJJ^^^ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^W[BpRDEEEEEEEEEEEEEEEEEEEEED4}M\X[[YZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[ZZZTTT\\\ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^V[CoRDEEEEEEEEEEEEEEEEEEEEEEEEEEEMeV\X[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^^^CXXX[[[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[YZ\X[2MDEEEEEEEEEEEEEEEEEEED0LZZZ[YZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[ZZZUUU]]][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Z[^W\@sRDEEEEEEEEEEEEEEEEEEEEEEEEEENfV]Y\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[___C+++___[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\Y[W^Z%HDEEEEEEEEEEEEEEEEED0L[[[\Y[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\[[[UUU]]][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[_X\@sRDEEEEEEEEEEEEEEEEEEEEEEEEENfV]Y\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[___C2DDD```[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[^X\KhUEEEEEEEEEEEEEEEEED,KY\Z]Y\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\[[[UUU]]][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\[\[\_Y]@sRDEEEEEEEEEEEEEEEEEEEEEEEENfV]Y\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[___CsWWW^^^[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[_X]=wPDEEEEEEEEEEEEEED,JY^[^Z\[\[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\[[[VVV^^^\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\`Y]@sRDEEEEEEEEEEEEEEEEEEEEEEEOgW^Z]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\```C%%%```\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\][\\[\,KDEEEEEEEEEEEED,JY^[^Z]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]]]\\\VVV^^^\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]\\`Y]AtRDEEEEEEEEEEEEEEEEEEEEEEOgW^Z]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\```C$@@@aaa\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\^Z]TcY FDEEEEEEEEEEC,KY_[^Z]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\]]]\\\WWW___]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`Z^AtSDEEEEEEEEEEEEEEEEEEEEEPhX_[^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]aaaCc UUU```]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]aY^FoUDEEEEEEEEED-KZ`\_[^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^]]]WWW___]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]aY^AtRDDEEEEEEEEEEEEEEEEEEEPhX_[^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]aaaC```^^^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`Z^6~NDEEEEEEED1L]^]_[^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^]]]WWW___]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^]]aZ^EqUEDEEEEEEEEEEEEEEEEEEPhX_[^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]aaaC:::ccc]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]_\^Z_\'IDEEEEEC1M]^]_\^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^]]]XXX```^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^b[`GpUEDEEEEEEEEEEEEEEEEEPiY`\_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^bbbCORRRaaa^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^a\_OiXEDEEEC7}O_]^`]_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___^^^XXX```^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^bZ_LlWFDEEEEEEEEEEEEEEEEPiY`\_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^bbbC```___^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^b[_@vSDEED:zP`\__]^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___^^^YYYaaa______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________b\`QjZ!HDEEEEEEEEEEEEEEEQjZa]`_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________cccC444ddd_____________________________________________________________________________________________________________________________________________________________________________________^_a]_0LCD?xRb\``^____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________```___YYYaaa_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________c\`Ug[&IDEEEEEEEEEEEEEEQjZa]`_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________cccC@MMMccc____________________________________________________________________________________________________________________________________________________________________________________a]`Wf\%ICuTc\``________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________```___YYYaaa____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________c]`Yd]+KCEEEEEEEEEEEEEQjZa]`_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________cccC___aaa____________________________________________________________________________________________________________________________________________________________________________________a^`[b^a^`____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________```___ZZZbbb```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````c^a^a_2NCEEEEEEEEEEEERjZb^a`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````dddC---fff```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````a_````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````aaa```ZZZbbb``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````b^aa_`9}PDEEEEEEEEEEERjZb^a`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````dddC1GGGeee``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````aaa```[[[cccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`aab_ad^aBwTDDEEEEEEEEESk[c_baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeeeCs\\\cccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbaaa[[[cccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab`ae^bLpXFDEEEEEEEESk[d_baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeeeC'''fffaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbaaa[[[cccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaae^cUj\&ICEEEEEEESk[d_baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeeeC"BBBgggaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbaaa[[[dddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbe_c]e`1MDEEEEEETl\e`cbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbfffC` YYYeeebbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccbbb[[[dddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbd`ccab=}SDDEEEETl\e`cbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbfffC eeecccbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccbbb\\\eeecccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccdbcg`dIuXFDEEEUm]fadcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccgggC<<PPPiiidddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeeeddd^^^gggeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeegcffdeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeiiiCcccgggeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeefffeee^^^gggeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeiiiC///jjjeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeefffeee^^^gggeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeiiiC/LLLkkkeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeefffeee___hhhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffkkkCoaaaiiiffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffgggfff___hhhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffkkkC'''kkkgggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffgggfff^^^iiigggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggglllC!EEEmmmggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghhhfffWWWjjjgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggglllC] ]]]jjjgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghhhcccSSSkkkgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggglllC!!!jjjhhhgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggiiibbb LLLmmmhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhmmmC>>>nnnhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhjjj___DDDnnnhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhmmmCKYYYlllhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhkkkWWW;;;oooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiinnnCjjjjjjiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiimmmNNN...nnniiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiinnnC 777oooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioooCCCb llliiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiinnnC<SSSnnniiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiooo666?jjjkkkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjoooChhhllljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjnnn'''t ___mmmjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjoooC000pppjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkL SSSoookkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkpppC+MMMqqqkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkmmmccc '???pppkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkpppCldddnnnkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkoooSSS(((qqqkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkpppC***ppplllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkppp@@@TjjjmmmllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllqqqCGGGrrrlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllqqq&&&([[[ooollllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllqqqCZ aaaooolllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllmmmhhhRDDDsssmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmrrrC"""ooonnnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmpppYYY"(((rrrmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmrrrCAAAtttmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmttt>>>X hhhooommmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmrrrCI]]]rrrmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnqqqPPPtttnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnsssCnnnpppnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnqqqaaaH...tttnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnsssC 999uuunnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnuuuBBBn jjjqqqooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooootttC:WWWtttoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooorrr#MMMuuuooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooootttC|lllqqqoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooorrr```P$$$tttpppoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooootttC000uuupppooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooovvv;;;e```tttpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppuuuC+QQQvvvppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppqqqnnn888wwwpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppuuuCliiissspppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppvvvNNN> kkksssqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvvvC***vvvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrttt:BBBxxxqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvvvCJJJwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvvvXXXkooorrrqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvvvCY eeeuuuqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqwww(((UHHHyyyrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwC"""vvvsssrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwww]]]nnntttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwCCCCyyyrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrssswww$$$!fAAAzzzssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssxxxCEaaaxxxssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssyyyWWW iiivvvsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssxxxCsssuuusssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssstttuuu%Z111zzzsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssxxxC :::{{{ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss{{{GGGZZZyyyttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttyyyC6ZZZzzzttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttwwwkkk DtttvvvtttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttyyyC{qqqvvvtttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttzzz...v===|||uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuzzzC333{{{uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu|||TTT "___{{{uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuzzzC)TTT|||uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuxxxmmmJprrrxxxuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuzzzCimmmyyyuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvvzzz***///|||wwwvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv{{{C+++{{{wwwvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv}}}GGG,JJJ~~~vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv{{{CLLL}}}vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv|||^^^Wn]]]}}}vvvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww|||CV iii{{{wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww{{{ooolll|||wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww|||C"""zzzxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwyyywww"""ssszzzwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww|||CDDDwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxx|||...7;&&&zzz{{{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}}}CEccc}}}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyy;;;if---yyyzzzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}}}Cxxxyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyy~~~BBB222~~~{{{yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy~~~C <<555rrr}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} CCggg}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}~~~zzzDDD`GGGyyy~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C|||}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}}~~~~~~TTT/oPPP|||~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C >>>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\\ /KKKwww~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C4```~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}}WWW!!!Ir@@@mmm!!!CvzzzuuuKKK#***XXXyyy!!!C555}}}```444 =I777]]]yyy!!!C&XXX}}}ccc===`[///QQQlll~~~!!!CcvvvqqqXXX555w i000LLLcccsss"""C,,,wwwfffRRR666Y '''999HHHSSS^^^gggmmmvvvyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx~~~CMMM}}}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyywwwnnniii___VVVJJJ===,,, k= CS NgCz'$nC~2WCBf'*TD_2 !=b? jF%???????~~|xxp``@`ppx||~????????libfreenect-0.5.3/wrappers/csharp/src/test/KinectDemo/openkinect_logo.png000066400000000000000000000137521264163024100266100ustar00rootroot00000000000000PNG  IHDR``w8sBIT|d pHYsaa?itEXtSoftwarewww.inkscape.org<gIDATx]k]Wu;O{2qLc21y$ I $( Bi)" T*jUD) H@HxA&'@$RАGlcIl^9x3'skǷ93$"M@D8~1Ƭpų&"O-MDǒ$a`;֟rƍmB/jZu)@DyF ݓ$ 0<<T<2| C39BϠ@Eߋ;hꪫ 쩹pjz{^{WXزeKw~?~$&ȋS9DN#_}[oUJ)sЂhR___-[f"͛iӦ'xbO?+"z<6i)7S)sW^ ` ?WmZ!R۷Zn"mݦ.⎝;w08JGx``ږ(F"T)u]wUjkkk}u" "{\sM)|%z Av`ʂ8qΛneȂ9sAd!˘۶m+q\H{~RDZ$HiY^J)ue5kҥ5TWFjczMysa3M@ T`Oqk6*FYF@0zt> \mR.- l (yz,ѕ[n-Dʛc &G@iSږA ҷŀ@9[QUooo!ҁW +@.3^s3 SP[C,H)(b ''X0߷ :pkR L ``z0o= ~vH[o%L qDt3mo{[@: ЊXyR!@r8x_sOOTr~"E D@EDԥW\ly Z#RZ+>NXe`49)@VtHGЊADAD`DH_B̮+PZ#R>H:X' b.UWin"DBL1p>@! %?d[l)h2JZC`0;_$CVUQx㛴҈tPCFDD+T*5=ڢt (͈/33@J?CAD'`+ȅo9Ub_X+03 (mιEq3nt).E7 ,YA+""@k8(XL|ԕ" Q`^Qñn{>BDjo,hS!YIWigA%ARm"9 ϽA+h8Lk(f0͈. da{ADt9`I)\ivPPT`>2X̰JAYVJ[WEs4Ql@ȧhӓGXf13{ʕ.*@97.*Cp'΍Oa " Жa/sҴڮ5+݌p>X@"Zo^n]GjڮFiu5M)`|fxʯÑV#}}ֹRR)V*M 畵=Fܹ?% :6M@+_ϢH#ٮ*D=$%G 0$ <+9+rdX"(ňVfggU4@D13gժU\lKݷ@G:(S6'P-C߇H@PA1C!& F柝Nr@&r""D`\B sLD5kj-eq7#ba3a']?[[_ HLY3@DŽxm#3'm'`VPZAe)E?`~z=I0BD[n.TAGRg@TWtk5 cOkdÿ &LG'Ǐ#{i6e/|,$0 ))(zI+iiDMDTOnz7vN$#9`ʈT%l$o:) .! i҉lԾygN /sk!j)ܺE"/uO{{owx/wt"GVT䱟90:o<H&g9! ԱBNLK5*V`\g䀏5#H~@A  moCxBEК93Te"M'@9(]4iٜ\BScH-"G uYVWr6XwPYPGl Q`WLh A]h ɪ}3Q<+&+ڊ/(JR鱢.†sv¥b[ &Qι \E>(^30zљjթ~R("[;r|! c>Bvlsn3F3H=XL|R呏ɭKuJ ʀuUF咛"l<ƫY褜)fz̓.7>^6sd2kXS(WA9"}{T";JuVL` .`ʟk@hZC;{9f(&R;;;; =Q TTӷ@мYG=%f-º=%k2RG A̒׬ UR&u Kޱ#F-'TϜlH|1JH*9"ˬH'jQ"7Bk<&&&L8lZ=,#jl*d%H4 vHFfoðL{vz )Y%e칮 𹱱Jq}c; κ藆aS S)V\2ggE ݌TfI1?sH\.G/gϬENiIy69MY3@D`+l|0E Z3"ݕJťiZhѣwZcV+,d6p. t͹9p c|pBʲd*dSDdOOLLTn=Qd'Xk9x9Q,ѹuc'N|j98:Ddw\6`Cc(2I,(KTElR0Q`p hX ^pV Ղx4"\{$1E(/xYi ޚv4z4l镜eQZJD%111Q- Eg8Ԅ 53s!jEy"3(_(7 AGmx'qySv'rRtȉ:zjAh蟩x o ŹC霺 AU8s`a%C.ی1_PI$v`H X-i1Vײg^Ld*s~!""'IRIBk~TGMM!C?%5R!K2 zҐsfseCQq:(djY*" EW+E(v3luSIqNVZcCPة6`Hx =|a|Z;scLC#ZCao nJK(~a*Al.1'5gj4UD,J%-W2#8Z&`躉x6 ;[NhDG>j^Z >Mv?BPػ|\.n؝[+O(9u#ΓA374A;Du7!+X~XdPq$I x9Xoca%Xˠ:Ϝ;Gʼtי=U !9g""C>dI9hՕ;2~ϟj+ED~Ƙ»V (Z) |o,I ۤΖWJVJ-F4m]Nl*$?#"נ<DDoڥ4[/~?E䨵v)i s R_""U"9 bCQ "ԩ$"""\~3~. Fi9 *D)|zF`"bxoғq/x>=jujED p) <`Lt<O[VLKDy 0 ܦ`à =3A c2jo$-Uu !p{Xwc4