pax_global_header00006660000000000000000000000064122174305300014507gustar00rootroot0000000000000052 comment=6198bcd469625cf7e10f2cddc7868b030e137249 libfreenect-0.2.0+dfsg/000077500000000000000000000000001221743053000147075ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/.gitignore000066400000000000000000000005361221743053000167030ustar00rootroot00000000000000#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.2.0+dfsg/APACHE20000066400000000000000000000261361221743053000157250ustar00rootroot00000000000000 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.2.0+dfsg/CMakeLists.txt000066400000000000000000000154121221743053000174520ustar00rootroot00000000000000###################################################################################### # 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 ###################################################################################### #Require 2.6 or higher. cmake_minimum_required(VERSION 2.6) ###################################################################################### # Project declaration and options ###################################################################################### PROJECT(libfreenect) set (PROJECT_VER_MAJOR 0) set (PROJECT_VER_MINOR 2) set (PROJECT_VER_PATCH 0) set (PROJECT_VER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}.${PROJECT_VER_PATCH}") set (PROJECT_APIVER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}") OPTION(BUILD_AUDIO "Build audio support" OFF) OPTION(BUILD_REDIST_PACKAGE "Build libfreenect in a legally-redistributable manner (only affects audio)" OFF) 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) IF(PROJECT_OS_LINUX) OPTION(BUILD_CPACK "Build an RPM or DEB using CPack" OFF) ENDIF(PROJECT_OS_LINUX) ###################################################################################### # CMake Modules ###################################################################################### 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) # 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(BUILD_AUDIO) add_definitions(-DBUILD_AUDIO) 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) # let CFLAGS env override this if(CMAKE_C_FLAGS STREQUAL "") set(CMAKE_C_FLAGS "-O2") endif() SET(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG=1") SET(CMAKE_C_FLAGS_RELEASE "-O2") SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g") add_definitions(-Wall) # 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") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/platform/windows/libusb10emu/libusb-1.0") endif() # Add library project add_subdirectory (src) # Add examples 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() ###################################################################################### # Extras ###################################################################################### # Create an uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/UninstallTarget.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/UninstallTarget.cmake" IMMEDIATE @ONLY) 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 ) 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 "DEB;RPM;") 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}) if (BUILD_AUDIO) INSTALL(FILES "include/libfreenect-audio.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) endif() INSTALL(FILES "include/libfreenect.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) INSTALL(FILES "include/libfreenect-registration.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.asciidoc" DESTINATION "share/doc/${CPACK_PACKAGE_NAME}") ENDIF ( BUILD_CPACK ) libfreenect-0.2.0+dfsg/CONTRIB000066400000000000000000000036521221743053000157400ustar00rootroot00000000000000The 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.2.0+dfsg/GPL2000066400000000000000000000431331221743053000153420ustar00rootroot00000000000000 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.2.0+dfsg/HACKING000066400000000000000000000051431221743053000157010ustar00rootroot00000000000000 "Coding styles are like assholes, everyone has one and no one likes anyone else's." --Eric Warmenhoven We're not terribly particular about coding style at this early stage. However, you should try to follow the following basic guidelines: === INDENTATION === libfreenect is coded using tabs for indentation. The nominal width is 4 spaces. However, you are encouraged to use spaces for alignment, as in the following example: if (foo(this, that, there) && bar == baz) { dostuff(); } Notice the spaces before the second line of the if() condition, after a single tab. This lets people use their preferred tab width setting while maintaining alignment. Do not, however, use spaces for indentation. Always use tabs. === WIDTH === We're not particular about code width, but 80 characters is a good mark where you should begin to consider breaking into multiple lines. A few 100 or 120-char lines are fine, but don't go longer than that. Documentation, if linewrapped, should be linewrapped to 80 character lines. === IF / FOR / WHILE / etc. === Put the opening brace on the same line, like this: if (foo) { ... } else if (bar) { ... } else { ... } Or don't use braces for single-line bodies, like this: if (foo) ... else if (bar) ... else ... Exceptions are allowed when the if() condition spans multiple lines and putting the brace on its own line looks better by visually separating the condition from the body. === FUNCTIONS === Functions should have the opening brace on the next line, like this: void foo(int a_thing, int something_else) { ... } No-args functions should be (void), and function arguments should be separated with a space after the comma, like this: void baz(void) { foo(bluh, blah); } Try to avoid having excessively long function names (abbreviating is fine) and don't make multiple functions that do essentially the same thing (and certainly don't copy and paste the code). In general, for data obtained with the Kinect, we'll provide a raw and a "cooked" variant, where it makes sense, but we don't need to support every "cooked" value convention under the sun. === WHITESPACE === Avoid trailing whitespace. No lines should end in a tab or a space. Keep a newline (blank line) at the end of each file. === DEBUG BUILD === In order to build the binaries with debug symbols the following commands can be used: $ mkdir build $ cd build $ cmake ../ -DCMAKE_BUILD_TYPE=debug $ make If you want to build in release mode (with optimizations) but still have debug symbols, try RelWithDebInfo: $ mkdir build $ cd build $ cmake ../ -DCMAKE_BUILD_TYPE=RelWithDebInfo $ make libfreenect-0.2.0+dfsg/README.asciidoc000066400000000000000000000071651221743053000173550ustar00rootroot00000000000000== libfreenect 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) === Description libfreenect is the core library for accessing the Microsoft Kinect USB camera. Currently, the library supports access to: - RGB and Depth Images - Motors - Accelerometer - LED Audio is currently being worked on. === Information Resources 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 We are also on twitter at http://twitter.com/openkinect === Requirements For the driver, you'll need - libusb-1.0 >= 1.0.9 (*nix and OS X) - libusb-win32 (Windows) - Cmake >= 2.6 (All platforms) For the glview sample, you'll need - OpenGL - glut - pthreads (Either platform provided or pthread-win32 for windows) For links to the software listed, see http://openkinect.org/wiki/Getting_Started#Dependencies See the platform specifics section for other information specific to the platform you may be working on. === Basic Compiling Instructions To use CMake: - Make a directory somewhere. Like, say, 'build' in your repo directory. - Go into that directory - Type cmake .. - Watch the magic happen - After this, just run make and you'll be fine. - If you want to use an IDE or whatever, well, you'll figure it out. === Platform Specifics ==== OS X libusb is available through various package managers including homebrew and Macports. OpenGL and GLUT come as prebuilt frameworks. ==== Linux Should "just work" if you have the following packages installed: - libusb-1.0-dev If you want to see the glview example: - freeglut3-dev (or whatever freeglut dev package your distro has) - libxmu-dev - libxi-dev udev rules are available in the platform/linux directory so that you are not required to run as root. ==== Windows Windows support is now available in libfreenect. The inf files in the platform/windows directory can be used for installing the device, and the library will need libusb-win32 to compile. ==== Wrappers libfreenect has interface to several languages. Look in the wrappers/ directory for them: - C (using a synchronous API) - C++ - C# - python - actionscript - Java (JNA) === Licensing 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. ---------- libfreenect-0.2.0+dfsg/cmake_modules/000077500000000000000000000000001221743053000175175ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/cmake_modules/FindOS.cmake000066400000000000000000000037331221743053000216510ustar00rootroot00000000000000# 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.2.0+dfsg/cmake_modules/FindThreads.cmake000066400000000000000000000207251221743053000227220ustar00rootroot00000000000000# 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.2.0+dfsg/cmake_modules/Findlibusb-1.0.cmake000066400000000000000000000065641221743053000231110ustar00rootroot00000000000000# - 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.2.0+dfsg/cmake_modules/SetupDirectories.cmake000066400000000000000000000020271221743053000240170ustar00rootroot00000000000000# 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) MESSAGE (STATUS "${PROJECT_NAME} will be installed to ${CMAKE_INSTALL_PREFIX}") # Installation prefix for include files STRING (TOLOWER ${PROJECT_NAME} projectNameLower) SET (PROJECT_INCLUDE_INSTALL_DIR "include/${projectNameLower}") IF (PROJECT_PROC_64BIT) SET (LIB_SUFFIX "64" CACHE STRING "Suffix for library installation directory") ELSE (PROJECT_PROC_64BIT) SET (LIB_SUFFIX "" CACHE STRING "Suffix for library installation directory") ENDIF (PROJECT_PROC_64BIT) SET (PROJECT_LIBRARY_INSTALL_DIR "lib${LIB_SUFFIX}") 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.2.0+dfsg/cmake_modules/UninstallTarget.cmake.in000066400000000000000000000017371221743053000242560ustar00rootroot00000000000000if (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.2.0+dfsg/doc/000077500000000000000000000000001221743053000154545ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/doc/Doxyfile000066400000000000000000002133141221743053000171660ustar00rootroot00000000000000# 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.2.0+dfsg/doc/DoxygenMainpage.h000066400000000000000000000033221221743053000207040ustar00rootroot00000000000000/** @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.2.0+dfsg/doc/astyle.conf000066400000000000000000000005771221743053000176350ustar00rootroot00000000000000# 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.2.0+dfsg/examples/000077500000000000000000000000001221743053000165255ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/examples/CMakeLists.txt000066400000000000000000000060241221743053000212670ustar00rootroot00000000000000###################################################################################### # Packages needed for examples ###################################################################################### set(CMAKE_C_FLAGS "-Wall") if (WIN32) set_source_files_properties(glview.c PROPERTIES LANGUAGE CXX) set_source_files_properties(regview.c PROPERTIES LANGUAGE CXX) set_source_files_properties(glpclview.c PROPERTIES LANGUAGE CXX) set_source_files_properties(hiview.c PROPERTIES LANGUAGE CXX) set_source_files_properties(tiltdemo.c PROPERTIES LANGUAGE CXX) set(THREADS_USE_PTHREADS_WIN32 true) find_package(Threads REQUIRED) include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) endif() add_executable(glview glview.c) add_executable(regview regview.c) add_executable(hiview hiview.c) if(BUILD_AUDIO) add_executable(wavrecord wavrecord.c) add_executable(micview micview.c) endif() if (BUILD_C_SYNC) add_executable(glpclview glpclview.c) add_executable(tiltdemo tiltdemo.c) add_executable(regtest regtest.c) endif() # We need to include libfreenect_sync.h for glpclview include_directories (../wrappers/c_sync/) # Mac just has everything already if(APPLE) set(CMAKE_EXE_LINKER_FLAGS "-framework OpenGL -framework GLUT") target_link_libraries(glview freenect) target_link_libraries(regview freenect) target_link_libraries(hiview freenect) if (BUILD_AUDIO) target_link_libraries(wavrecord freenect) target_link_libraries(micview freenect) endif() if (BUILD_C_SYNC) target_link_libraries(glpclview freenect_sync) target_link_libraries(tiltdemo freenect_sync) target_link_libraries(regtest freenect_sync) endif() # Linux, not so much else() find_package(Threads REQUIRED) find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS}) target_link_libraries(glview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(regview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(hiview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) if (BUILD_AUDIO) target_link_libraries(wavrecord freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(micview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) endif() if (BUILD_C_SYNC) target_link_libraries(glpclview freenect_sync ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(tiltdemo freenect_sync ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(regtest freenect_sync ${CMAKE_THREAD_LIBS_INIT}) endif() endif() install (TARGETS glview regview hiview DESTINATION bin) if (BUILD_C_SYNC) install (TARGETS glpclview tiltdemo DESTINATION bin) endif() if (BUILD_AUDIO) install (TARGETS wavrecord DESTINATION bin) install (TARGETS micview DESTINATION bin) endif() libfreenect-0.2.0+dfsg/examples/glpclview.c000066400000000000000000000141441221743053000206710ustar00rootroot00000000000000/* * 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 #if defined(__APPLE__) #include #include #include #else #include #include #include #endif #include #include 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.2.0+dfsg/examples/glview.c000066400000000000000000000274551221743053000202030ustar00rootroot00000000000000/* * 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 #include #include #else #include #include #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; 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; 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); 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_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); glBegin(GL_TRIANGLE_FAN); glColor4f(1.0f, 1.0f, 1.0f, 1.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) { 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; } } if (key == 's') { freenect_angle = 0; } 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; } } 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; } 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; } 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; } 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; } 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, 1280, 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); 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, 'f'-video format\n"); printf("'e' - auto exposure, 'b' - white balance, 'r' - raw color, 'm' - mirror\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.2.0+dfsg/examples/hiview.c000066400000000000000000000310371221743053000201700ustar00rootroot00000000000000/* * 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 #include #include #else #include #include #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.2.0+dfsg/examples/micview.c000066400000000000000000000155211221743053000203400ustar00rootroot00000000000000/* * 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 #include 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] = malloc(state.max_samples * sizeof(int32_t)); state.buffers[1] = malloc(state.max_samples * sizeof(int32_t)); state.buffers[2] = malloc(state.max_samples * sizeof(int32_t)); state.buffers[3] = 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.2.0+dfsg/examples/regtest.c000066400000000000000000000053521221743053000203530ustar00rootroot00000000000000/* * 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.2.0+dfsg/examples/regview.c000066400000000000000000000225141221743053000203450ustar00rootroot00000000000000/* * 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 #if defined(__APPLE__) #include #include #include #else #include #include #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; 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 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-ftime)/1000.0); 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.2.0+dfsg/examples/tiltdemo.c000066400000000000000000000104701221743053000205140ustar00rootroot00000000000000/* * 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.2.0+dfsg/examples/wavrecord.c000066400000000000000000000117021221743053000206660ustar00rootroot00000000000000/* * 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.2.0+dfsg/fakenect/000077500000000000000000000000001221743053000164675ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/fakenect/CMakeLists.txt000066400000000000000000000015561221743053000212360ustar00rootroot00000000000000###################################################################################### # 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(record record.c) target_link_libraries(record freenect) install (TARGETS record DESTINATION bin) CONFIGURE_FILE("fakenect.sh.in" "fakenect.sh" IMMEDIATE @ONLY) install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fakenect.sh DESTINATION bin RENAME fakenect) libfreenect-0.2.0+dfsg/fakenect/README000066400000000000000000000055011221743053000173500ustar00rootroot00000000000000Fakenect (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.2.0+dfsg/fakenect/fakenect.c000066400000000000000000000266741221743053000204320ustar00rootroot00000000000000/* * 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 #include #include #include #include #include #include #include #ifdef _WIN32 #include #endif #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 = {}; 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 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 } static 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 } static char *one_line(FILE *fp) { int pos = 0; char *out = NULL; char c; while ((c = fgetc(fp))) { if (c == '\n' || c == EOF) break; 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 *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"); return -1; } fclose(cur_fp); free(line); free(file_path); return 0; } 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; } 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; } 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; } 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_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_init(freenect_context **ctx, freenect_usb_context *usb_ctx) { *ctx = fake_ctx; return 0; } 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.2.0+dfsg/fakenect/fakenect.sh.in000077500000000000000000000036011221743053000212130ustar00rootroot00000000000000#!/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/:${LD_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.2.0+dfsg/fakenect/record.c000066400000000000000000000223031221743053000201110ustar00rootroot00000000000000/* * 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 #include #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; double get_time() { struct timeval cur; gettimeofday(&cur, NULL); return cur.tv_sec + cur.tv_usec / 1000000.; } 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; void *end = data + data_size; while (data < end) { z = *(unsigned short*)data; fwrite(((char*)(&z)), 3, 1, stream); data += 2; } } void snapshot_accel(freenect_device *dev) { if (!last_timestamp) return; freenect_raw_tilt_state* state; 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); if (!index_fp) return 1; free(index_fn); 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); if (!index_fp) return 1; free(fn); init(); fclose(index_fp); } return 0; } libfreenect-0.2.0+dfsg/include/000077500000000000000000000000001221743053000163325ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/include/libfreenect-audio.h000066400000000000000000000110631221743053000220650ustar00rootroot00000000000000/* * 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 #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.2.0+dfsg/include/libfreenect-registration.h000066400000000000000000000070041221743053000234760ustar00rootroot00000000000000/* * 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 #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); #ifdef __cplusplus } #endif libfreenect-0.2.0+dfsg/include/libfreenect.h000066400000000000000000000617611221743053000210000ustar00rootroot00000000000000/* * 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 { struct freenect_device_attributes *next; /**< Next device in the linked list */ const char* camera_serial; /**< Serial number of this device's camera 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, // registers to be written with 0 or 1 FREENECT_MIRROR_DEPTH = 0x0017, FREENECT_MIRROR_VIDEO = 0x0047, } 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); /** * 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 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); #ifdef __cplusplus } #endif libfreenect-0.2.0+dfsg/mkcontrib.sh000066400000000000000000000005761221743053000172430ustar00rootroot00000000000000#!/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.2.0+dfsg/platform/000077500000000000000000000000001221743053000165335ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/platform/linux/000077500000000000000000000000001221743053000176725ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/platform/linux/udev/000077500000000000000000000000001221743053000206355ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/platform/linux/udev/51-kinect.rules000066400000000000000000000011271221743053000234120ustar00rootroot00000000000000# 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.2.0+dfsg/platform/linux/udev/README000066400000000000000000000001401221743053000215100ustar00rootroot00000000000000Simply place this file in /etc/udev/rules.d and you'll no longer need to run your apps as root. libfreenect-0.2.0+dfsg/platform/windows/000077500000000000000000000000001221743053000202255ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/platform/windows/README.TXT000066400000000000000000000430601221743053000215660ustar00rootroot00000000000000====================================================================================== 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.2.0+dfsg/platform/windows/libusb10emu/000077500000000000000000000000001221743053000223555ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/000077500000000000000000000000001221743053000241315ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/failguard.cpp000066400000000000000000000032401221743053000265720ustar00rootroot00000000000000#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.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/failguard.h000066400000000000000000000002171221743053000262400ustar00rootroot00000000000000#pragma once namespace libusbemu { namespace failguard { const bool Check(); void WaitDecision(); const bool Abort(); } } libfreenect-0.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/libusb.h000066400000000000000000000153301221743053000255640ustar00rootroot00000000000000/* * 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.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp000066400000000000000000001056351221743053000266360ustar00rootroot00000000000000/* * 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.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/libusbemu_internal.h000066400000000000000000000250261221743053000301720ustar00rootroot00000000000000/* * 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.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/libusbemu_threads.h000066400000000000000000000040051221743053000300020ustar00rootroot00000000000000/* * 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.2.0+dfsg/platform/windows/libusb10emu/libusb-1.0/libusbemu_threads_win32.h000066400000000000000000000200111221743053000310170ustar00rootroot00000000000000/* * 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.2.0+dfsg/platform/windows/unistd.h000066400000000000000000000025151221743053000217070ustar00rootroot00000000000000/* * 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 // MinGW defines _SSIZE_T_ 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_ #define _SSIZE_T_ typedef long ssize_t; #endif // _SSIZE_T_ libfreenect-0.2.0+dfsg/src/000077500000000000000000000000001221743053000154765ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/src/CMakeLists.txt000066400000000000000000000053301221743053000202370ustar00rootroot00000000000000###################################################################################### # Build for main library ###################################################################################### include_directories (${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_C_FLAGS "-Wall") include_directories(${LIBUSB_1_INCLUDE_DIRS}) IF(WIN32) LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c ../platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp ../platform/windows/libusb10emu/libusb-1.0/failguard.cpp) set_source_files_properties(${SRC} PROPERTIES LANGUAGE CXX) ELSE(WIN32) LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c) ENDIF(WIN32) IF(BUILD_AUDIO) include(FindPythonInterp) LIST(APPEND SRC audio.c loader.c) 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() ENDIF() 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" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) if(BUILD_AUDIO) install (FILES "../include/libfreenect-audio.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR}) endif() IF(UNIX AND NOT APPLE) # 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.2.0+dfsg/src/audio.c000066400000000000000000000176271221743053000167600ustar00rootroot00000000000000/* * 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.2.0+dfsg/src/cameras.c000066400000000000000000001264451221743053000172710ustar00rootroot00000000000000/* * 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) { 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; FN_LOG(l_info, "[Stream %02x] Lost %d packets\n", strm->flag, lost); 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 data uint8_t *dbuf = strm->raw_buf + strm->pkt_num * strm->pkt_size; 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); 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); 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.4; return 0; } int freenect_start_depth(freenect_device *dev) { freenect_context *ctx = dev->parent; int res; 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; } res = fnusb_start_iso(&dev->usb_cam, &dev->depth_isoc, depth_process, 0x82, NUM_XFERS, PKTS_PER_XFER, DEPTH_PKTBUF); 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; int res; 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; } res = fnusb_start_iso(&dev->usb_cam, &dev->video_isoc, video_process, 0x81, NUM_XFERS, PKTS_PER_XFER, VIDEO_PKTBUF); 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; freenect_destroy_registration(&(dev->registration)); 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; } 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; } 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.2.0+dfsg/src/cameras.h000066400000000000000000000025711221743053000172670ustar00rootroot00000000000000/* * 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.2.0+dfsg/src/core.c000066400000000000000000000166421221743053000166030ustar00rootroot00000000000000/* * 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" #ifdef BUILD_AUDIO #include "loader.h" #endif FREENECTAPI int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx) { int res; *ctx = (freenect_context*)malloc(sizeof(freenect_context)); if (!ctx) 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 #ifdef BUILD_AUDIO | FREENECT_DEVICE_AUDIO #endif ); 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); } #ifdef BUILD_AUDIO 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); } #endif 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) { #ifdef BUILD_AUDIO return FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA | FREENECT_DEVICE_AUDIO; #else return FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA; #endif } 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 #ifdef BUILD_AUDIO | FREENECT_DEVICE_AUDIO #endif )); } 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 -1; } 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); } } libfreenect-0.2.0+dfsg/src/flags.c000066400000000000000000000130741221743053000167430ustar00rootroot00000000000000/* * 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 "freenect_internal.h" #include "flags.h" // freenect_set_flag is the only function exposed in libfreenect.h // The rest are available internally via #include flags.h int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value) { if (flag == FREENECT_MIRROR_DEPTH || flag == FREENECT_MIRROR_VIDEO) return write_register(dev, flag, value); uint16_t reg = read_cmos_register(dev, 0x0106); if (reg < 0) return reg; if (value == FREENECT_ON) reg |= flag; else reg &= ~flag; return write_cmos_register(dev, 0x0106, reg); } 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; } FN_INTERNAL uint16_t read_register(freenect_device *dev, uint16_t reg) { freenect_context *ctx = dev->parent; uint16_t reply[2]; uint16_t cmd; int res; cmd = fn_le16(reg); FN_DEBUG("read_register: 0x%04x =>\n", reg); res = send_cmd(dev, 0x02, &cmd, 2, reply, 4); if (res < 0) FN_ERROR("read_register: send_cmd() failed: %d\n", res); if (res != 4) FN_WARNING("read_register: send_cmd() returned %d [%04x %04x], 0000 expected\n", res, reply[0], 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]; int res; cmd[0] = fn_le16(reg); cmd[1] = fn_le16(data); FN_DEBUG("write_register: 0x%04x <= 0x%02x\n", reg, data); res = send_cmd(dev, 0x03, cmd, 4, reply, 4); if (res < 0) return res; if (res != 2) { FN_WARNING("send_cmd() returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); } return 0; } 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 res; } 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; 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 res; } libfreenect-0.2.0+dfsg/src/flags.h000066400000000000000000000030031221743053000167370ustar00rootroot00000000000000/* * 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); uint16_t read_register(freenect_device *dev, uint16_t reg); int write_register(freenect_device *dev, uint16_t reg, uint16_t data); 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.2.0+dfsg/src/freenect_internal.h000066400000000000000000000143511221743053000213420ustar00rootroot00000000000000/* * 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" #ifdef BUILD_AUDIO #include "libfreenect-audio.h" #endif #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" 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; }; #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 #define PID_K4W_AUDIO 0x02be 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; 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; #ifdef BUILD_AUDIO 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; #endif 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_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; #ifdef BUILD_AUDIO // 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; #endif // Motor fnusb_dev usb_motor; freenect_raw_tilt_state raw_state; }; libfreenect-0.2.0+dfsg/src/fwfetcher.py000066400000000000000000000465021221743053000200340ustar00rootroot00000000000000#!/usr/bin/env python 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.2.0+dfsg/src/libfreenect.pc.in000066400000000000000000000005421221743053000207120ustar00rootroot00000000000000prefix=@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.2.0+dfsg/src/loader.c000066400000000000000000000272541221743053000171220ustar00rootroot00000000000000/* * 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) { freenect_context* ctx = dev->parent->parent; bootloader_command bootcmd; memset(&bootcmd, 0, sizeof(bootcmd)); bootcmd.magic = fn_le32(0x06022009); int res; int transferred; /* Search for firmware file (audios.bin) in the following places: * $LIBFREENECT_FIRMWARE_PATH * . * ${HOME}/.libfreenect * /usr/local/share/libfreenect * /usr/share/libfreenect */ const char* fw_filename = "/audios.bin"; int filenamelen = strlen(fw_filename); int i; int searchpathcount; FILE* fw = NULL; for(i = 0, searchpathcount = 5; !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 = malloc(pathlen + filenamelen + 1); strcpy(fwfile, envpath); strcat(fwfile, fw_filename); needs_free = 1; } break; case 1: fwfile = "./audios.bin"; 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"; break; case 4: fwfile = "/usr/share/libfreenect/audios.bin"; 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; } // Now we have an open firmware file handle. firmware_header fwheader; int read = 0; read = fread(&fwheader, 1, sizeof(firmware_header), fw); if (read != sizeof(firmware_header)) { FN_ERROR("upload_firmware: firmware image too small, has no header?\n"); fclose(fw); return -errno; } // 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); rewind(fw); uint32_t addr = fwheader.base_addr; unsigned char page[0x4000]; int total_bytes_sent = 0; do { size_t block_size = (0x4000 > fwheader.size - total_bytes_sent) ? fwheader.size - total_bytes_sent : 0x4000; read = fread(page, 1, block_size, fw); if(read <= 0) { break; } 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))); fclose(fw); 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); fclose(fw); 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); fclose(fw); fw = NULL; 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.2.0+dfsg/src/loader.h000066400000000000000000000043441221743053000171220ustar00rootroot00000000000000/* * 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); int upload_cemd_data(fnusb_dev* dev); libfreenect-0.2.0+dfsg/src/registration.c000066400000000000000000000334061221743053000203620ustar00rootroot00000000000000/* * 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 "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; } /// 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.2.0+dfsg/src/registration.h000066400000000000000000000026521221743053000203660ustar00rootroot00000000000000/* * 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.2.0+dfsg/src/tilt.c000066400000000000000000000072641221743053000166270ustar00rootroot00000000000000/* * 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 freenect_raw_tilt_state* freenect_get_tilt_state(freenect_device *dev) { return &dev->raw_state; } int freenect_update_tilt_state(freenect_device *dev) { freenect_context *ctx = dev->parent; 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(freenect_device *dev, double angle) { freenect_context *ctx = dev->parent; 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, (uint16_t)angle, 0x0, empty, 0x0); return ret; } int freenect_set_led(freenect_device *dev, freenect_led_options option) { freenect_context *ctx = dev->parent; 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.2.0+dfsg/src/usb_libusb10.c000066400000000000000000000465121221743053000201440ustar00rootroot00000000000000/* * 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" 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; } FN_INTERNAL int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_device_attributes** attribute_list) { *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** camera_prev_next = 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_devs. Likewise for each audio device. struct libusb_device_descriptor desc; int num_cams = 0; int i; for (i = 0; i < count; 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)) { // Verify that a serial number exists to query. If not, don't touch the device. if (desc.iSerialNumber == 0) { continue; } // Open device. int res; libusb_device_handle *this_device; res = libusb_open(devs[i], &this_device); unsigned char string_desc[256]; // String descriptors are at most 256 bytes. if (res != 0) { continue; } // Read string descriptor referring to serial number. res = libusb_get_string_descriptor_ascii(this_device, desc.iSerialNumber, string_desc, 256); libusb_close(this_device); if (res < 0) { continue; } // Add item to linked list. struct freenect_device_attributes* new_dev_attrs = (struct freenect_device_attributes*)malloc(sizeof(struct freenect_device_attributes)); memset(new_dev_attrs, 0, sizeof(*new_dev_attrs)); *camera_prev_next = new_dev_attrs; // Copy string with serial number new_dev_attrs->camera_serial = strdup((char*)string_desc); camera_prev_next = &(new_dev_attrs->next); // Increment number of cameras found 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); } FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) { freenect_context *ctx = dev->parent; dev->usb_cam.parent = dev; dev->usb_cam.dev = NULL; dev->usb_motor.parent = dev; dev->usb_motor.dev = NULL; #ifdef BUILD_AUDIO dev->usb_audio.parent = dev; dev->usb_audio.dev = NULL; #endif 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; #ifdef BUILD_AUDIO int nr_audio = 0; #endif 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) { 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)){ /* Not the old kinect so we only set up the camera*/ ctx->enabled_subdevices = FREENECT_DEVICE_CAMERA; ctx->zero_plane_res = 334; }else{ /* The good old kinect that tilts and tweets */ ctx->zero_plane_res = 322; } #ifndef _WIN32 // Detach an existing kernel driver for the device res = libusb_kernel_driver_active(dev->usb_cam.dev, 0); if (res == 1) { res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0); if (res < 0) { FN_ERROR("Could not detach kernel driver for camera: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } } #endif res = libusb_claim_interface (dev->usb_cam.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on camera: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } if(desc.idProduct == PID_K4W_CAMERA){ res = libusb_set_interface_alt_setting(dev->usb_cam.dev, 0, 1); if (res != 0) { FN_ERROR("Failed to set alternate interface #1 for K4W: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; 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) { 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++; } } #ifdef BUILD_AUDIO // TODO: check that the firmware has already been loaded; if not, upload firmware. // Search for the audio if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || desc.idProduct == PID_K4W_AUDIO)) { // If the index given by the user matches our audio index if (nr_audio == index) { 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 == 1) { // 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"); res = upload_firmware(&dev->usb_audio); 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++) { // Loop for at most 10 tries. 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) { 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. if (fnusb_num_interfaces(&dev->usb_audio) != 2) { 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++; } } #endif } libusb_free_device_list (devs, 1); // free the list, unref the devices in it // Check that each subdevice is either opened or not enabled. if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA)) && (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) #ifdef BUILD_AUDIO && (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO)) #endif ) { return 0; } else { if (dev->usb_cam.dev) { libusb_release_interface(dev->usb_cam.dev, 0); libusb_close(dev->usb_cam.dev); } if (dev->usb_motor.dev) { libusb_release_interface(dev->usb_motor.dev, 0); libusb_close(dev->usb_motor.dev); } #ifdef BUILD_AUDIO if (dev->usb_audio.dev) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); } #endif 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; } #ifdef BUILD_AUDIO if (dev->usb_audio.dev) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; } #endif return 0; } static void 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_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, int ep, int xfers, int pkts, int len) { freenect_context *ctx = dev->parent->parent; int ret, i; 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; uint8_t *bufp = strm->buffer; for (i=0; ixfers[i] = libusb_alloc_transfer(pkts); libusb_fill_iso_transfer(strm->xfers[i], dev->dev, ep, bufp, pkts * len, pkts, iso_callback, strm, 0); libusb_set_iso_packet_lengths(strm->xfers[i], len); 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"); memset(strm, 0, sizeof(*strm)); 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); } #ifdef BUILD_AUDIO 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; } #endif libfreenect-0.2.0+dfsg/src/usb_libusb10.h000066400000000000000000000067041221743053000201500ustar00rootroot00000000000000/* * 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 #if defined(__APPLE__) /* From Github Issue 22 by Roefer - https://github.com/OpenKinect/libfreenect/issues/#issue/22 The current implementation still does not reach 30 Hz on MacOS. This is due to bad scheduling of USB transfers in libusb (Ed Note: libusb 1.0.8). A fix can be found at http://www.informatik.uni-bremen.de/~roefer/libusb/libusb-osx-kinect.diff (Ed Note: patch applies to libusb repo at 7da756e09fd) In camera.c, I use PKTS_PER_XFER = 128, NUM_XFERS = 4. There are a few rules: PKTS_PER_XFER * NUM_XFERS <= 1000, PKTS_PER_XFER % 8 == 0. */ #define PKTS_PER_XFER 128 #define NUM_XFERS 4 #define DEPTH_PKTBUF 2048 #define VIDEO_PKTBUF 2048 #else #ifdef _WIN32 #define PKTS_PER_XFER 32 #define NUM_XFERS 8 #else #define PKTS_PER_XFER 16 #define NUM_XFERS 16 #endif #define DEPTH_PKTBUF 1920 #define VIDEO_PKTBUF 1920 #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) } 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, int ep, int xfers, int pkts, int len); int fnusb_stop_iso(fnusb_dev *dev, fnusb_isoc_stream *strm); int fnusb_control(fnusb_dev *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength); #ifdef BUILD_AUDIO int fnusb_bulk(fnusb_dev *dev, uint8_t endpoint, uint8_t *data, int len, int *transferred); int fnusb_num_interfaces(fnusb_dev *dev); #endif libfreenect-0.2.0+dfsg/wrappers/000077500000000000000000000000001221743053000165525ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/.gitignore000066400000000000000000000000071221743053000205370ustar00rootroot00000000000000/test/ libfreenect-0.2.0+dfsg/wrappers/actionscript/000077500000000000000000000000001221743053000212545ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/actionscript/CMakeLists.txt000077500000000000000000000020101221743053000240100ustar00rootroot00000000000000###################################################################################### # 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.2.0+dfsg/wrappers/actionscript/org/000077500000000000000000000000001221743053000220435ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/actionscript/org/as3kinect/000077500000000000000000000000001221743053000237275ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3KinectCalibrationUI.as000066400000000000000000000431221221743053000305100ustar00rootroot00000000000000package 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinect.as000077500000000000000000000056261221743053000261540ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectDepth.as000077500000000000000000000112231221743053000271270ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectMotor.as000077500000000000000000000070701221743053000271700ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectSocket.as000077500000000000000000000105751221743053000273240ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectUI.as000066400000000000000000000202161221743053000263770ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectUtils.as000077500000000000000000000316731221743053000271760ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectVideo.as000077500000000000000000000063211221743053000271340ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectWrapper.as000077500000000000000000000100151221743053000275010ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/as3kinectWrapperEvent.as000077500000000000000000000032271221743053000305120ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/events/000077500000000000000000000000001221743053000252335ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/actionscript/org/as3kinect/events/as3kinectCalibrationEvent.as000066400000000000000000000006711221743053000326220ustar00rootroot00000000000000package 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/events/as3kinectSocketEvent.as000077500000000000000000000027571221743053000316350ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/events/as3kinectWrapperEvent.as000077500000000000000000000032271221743053000320160ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/objects/000077500000000000000000000000001221743053000253605ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/actionscript/org/as3kinect/objects/PointWithID.as000066400000000000000000000005401221743053000300460ustar00rootroot00000000000000package 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/objects/as3kinectCalibrationParams.as000066400000000000000000000026051221743053000331100ustar00rootroot00000000000000package 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.2.0+dfsg/wrappers/actionscript/org/as3kinect/objects/motorData.as000077500000000000000000000026771221743053000276560ustar00rootroot00000000000000/* * * 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.2.0+dfsg/wrappers/actionscript/server/000077500000000000000000000000001221743053000225625ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/actionscript/server/as3-server.c000077500000000000000000000261111221743053000247240ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/actionscript/server/as3_jpeg.c000077500000000000000000000037351221743053000244340ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/actionscript/server/as3_jpeg.h000077500000000000000000000025101221743053000244270ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/actionscript/server/freenect_network.c000077500000000000000000000134061221743053000263010ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/actionscript/server/freenect_network.h000077500000000000000000000037061221743053000263100ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/c_sync/000077500000000000000000000000001221743053000200305ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/c_sync/CMakeLists.txt000066400000000000000000000021431221743053000225700ustar00rootroot00000000000000###################################################################################### # C Synchronous Interface ###################################################################################### if (WIN32) set_source_files_properties(libfreenect_sync.c PROPERTIES LANGUAGE CXX) set(THREADS_USE_PTHREADS_WIN32 true) endif() 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.2.0+dfsg/wrappers/c_sync/README000066400000000000000000000006171221743053000207140ustar00rootroot00000000000000** 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.2.0+dfsg/wrappers/c_sync/libfreenect_sync.c000066400000000000000000000300151221743053000235110ustar00rootroot00000000000000/* * 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_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; } 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] = {}; 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_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(FREENECT_RESOLUTION_MEDIUM, 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; return 0; } static int alloc_buffer_ring_depth(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(FREENECT_RESOLUTION_MEDIUM, 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; 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; } 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_video_format fmt) { freenect_stop_video(kinect->dev); free_buffer_ring(&kinect->video); if (alloc_buffer_ring_video(fmt, &kinect->video)) return -1; freenect_set_video_mode(kinect->dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, 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_depth_format fmt) { freenect_stop_depth(kinect->dev); free_buffer_ring(&kinect->depth); if (alloc_buffer_ring_depth(fmt, &kinect->depth)) return -1; freenect_set_depth_mode(kinect->dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, 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->depth.fmt = -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 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) { if (is_depth) change_depth_format(kinects[index], (freenect_depth_format)fmt); else change_video_format(kinects[index], (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_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(void **video, uint32_t *timestamp, int index, 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) if (setup_kinect(index, fmt, 0)) return -1; sync_get(video, timestamp, &kinects[index]->video); return 0; } int freenect_sync_get_depth(void **depth, uint32_t *timestamp, int index, 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) if (setup_kinect(index, fmt, 1)) return -1; sync_get(depth, timestamp, &kinects[index]->depth); return 0; } 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; } void freenect_sync_stop(void) { if (thread_running) { thread_running = 0; pthread_join(thread, NULL); } } libfreenect-0.2.0+dfsg/wrappers/c_sync/libfreenect_sync.h000066400000000000000000000064111221743053000235210ustar00rootroot00000000000000/* * 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 #include #ifdef __cplusplus extern "C" { #endif int freenect_sync_get_video(void **video, uint32_t *timestamp, int index, 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) fmt: Valid format Returns: Nonzero on error. */ int freenect_sync_get_depth(void **depth, uint32_t *timestamp, int index, 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) fmt: Valid format Returns: Nonzero on error. */ 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. */ 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. */ 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. */ void freenect_sync_stop(void); #ifdef __cplusplus } #endif libfreenect-0.2.0+dfsg/wrappers/cpp/000077500000000000000000000000001221743053000173345ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/cpp/CMakeLists.txt000066400000000000000000000014761221743053000221040ustar00rootroot00000000000000INSTALL(FILES libfreenect.hpp DESTINATION include) IF(BUILD_EXAMPLES) set(CMAKE_C_FLAGS "-Wall") if (WIN32) set(THREADS_USE_PTHREADS_WIN32 true) find_package(Threads REQUIRED) include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) endif() include_directories(.) add_executable(cppview cppview.cpp) # Mac just has everything already if(APPLE) set(CMAKE_EXE_LINKER_FLAGS "-framework OpenGL -framework GLUT") target_link_libraries(cppview freenect) else() find_package(Threads REQUIRED) find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS}) target_link_libraries(cppview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) endif() install (TARGETS cppview DESTINATION bin) ENDIF() libfreenect-0.2.0+dfsg/wrappers/cpp/cppview.cpp000077500000000000000000000216471221743053000215320ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/cpp/libfreenect.hpp000066400000000000000000000220031221743053000223240ustar00rootroot00000000000000/* * 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 #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); freenect_set_video_mode(m_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); freenect_set_depth_mode(m_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); 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) { freenect_stop_video(m_dev); 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"); 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) { freenect_stop_depth(m_dev); 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"); 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; } const freenect_device *getDevice() { return m_dev; } // Do not call directly even in child virtual void VideoCallback(void *video, uint32_t timestamp) = 0; // Do not call directly even in child virtual void DepthCallback(void *depth, uint32_t timestamp) = 0; 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() { for(DeviceMap::iterator it = m_devices.begin() ; it != m_devices.end() ; ++it) { delete it->second; } m_stop = true; 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.insert(std::make_pair(_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) { int res = freenect_process_events(m_ctx); 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; } private: freenect_context *m_ctx; volatile bool m_stop; pthread_t m_thread; DeviceMap m_devices; }; } libfreenect-0.2.0+dfsg/wrappers/csharp/000077500000000000000000000000001221743053000200325ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/README000066400000000000000000000004101221743053000207050ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/000077500000000000000000000000001221743053000206215ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/lib/000077500000000000000000000000001221743053000213675ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/lib/Accelerometer.cs000066400000000000000000000102031221743053000244640ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/AssemblyInfo.cs000066400000000000000000000017341221743053000243160ustar00rootroot00000000000000using 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.2.0+dfsg/wrappers/csharp/src/lib/BaseCamera.cs000066400000000000000000000110731221743053000237030ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/BaseDataMap.cs000066400000000000000000000063161221743053000240260ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/DepthCamera.cs000066400000000000000000000136121221743053000240760ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/DepthFrameMode.cs000066400000000000000000000042461221743053000245500ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/DepthMap.cs000066400000000000000000000033651221743053000234270ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/Enumerations.cs000066400000000000000000000050071221743053000243710ustar00rootroot00000000000000/* * 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 } /// /// 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.2.0+dfsg/wrappers/csharp/src/lib/FrameMode.cs000066400000000000000000000112041221743053000235530ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/ImageMap.cs000066400000000000000000000034511221743053000234010ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/Kinect.cs000066400000000000000000000202121221743053000231300ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/KinectNative.cs000066400000000000000000000252051221743053000243060ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/LED.cs000066400000000000000000000044621221743053000223300ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/LogEventArgs.cs000066400000000000000000000042661221743053000242660ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/Motor.cs000066400000000000000000000101051221743053000230130ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/SwapBufferCollection.cs000066400000000000000000000106261221743053000260030ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/VS2008/000077500000000000000000000000001221743053000222315ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/lib/VS2008/freenectdotnet.csproj000066400000000000000000000064031221743053000264670ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/lib/VS2008/freenectdotnet.sln000066400000000000000000000016431221743053000257640ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/lib/VS2010/000077500000000000000000000000001221743053000222225ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/lib/VS2010/freenectdotnet.csproj000066400000000000000000000141251221743053000264600ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/lib/VS2010/freenectdotnet.sln000066400000000000000000000025521221743053000257550ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/lib/VideoCamera.cs000066400000000000000000000140001221743053000240700ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/lib/VideoFrameMode.cs000066400000000000000000000042461221743053000245520ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/000077500000000000000000000000001221743053000216005ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/000077500000000000000000000000001221743053000240425ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/AssemblyInfo.cs000066400000000000000000000017211221743053000267650ustar00rootroot00000000000000using 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.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/Main.cs000066400000000000000000000060351221743053000252610ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/VS2008/000077500000000000000000000000001221743053000247045ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/VS2008/ConsoleTest.csproj000066400000000000000000000040631221743053000303730ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/VS2008/ConsoleTest.sln000066400000000000000000000015521221743053000276670ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/VS2010/000077500000000000000000000000001221743053000246755ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/VS2010/ConsoleTest.csproj000066400000000000000000000114001221743053000303550ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/ConsoleTest/VS2010/ConsoleTest.sln000066400000000000000000000036011221743053000276550ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/000077500000000000000000000000001221743053000236225ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/MainWindow.UI.cs000066400000000000000000000306431221743053000265470ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/MainWindow.cs000066400000000000000000000365741221743053000262440ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/PreviewControl.UI.cs000066400000000000000000000036421221743053000274540ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/PreviewControl.cs000066400000000000000000000305741221743053000271440ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/Program.cs000066400000000000000000000030211221743053000255540ustar00rootroot00000000000000/* * 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/VS2008/000077500000000000000000000000001221743053000244645ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/VS2008/KinectDemo.csproj000066400000000000000000000062721221743053000277370ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/VS2008/KinectDemo.sln000066400000000000000000000015471221743053000272330ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/VS2010/000077500000000000000000000000001221743053000244555ustar00rootroot00000000000000libfreenect-0.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/VS2010/KinectDemo.csproj000066400000000000000000000141351221743053000277250ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/VS2010/KinectDemo.sln000066400000000000000000000041621221743053000272200ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/openkinect_icon.ico000066400000000000000000054000261221743053000274740ustar00rootroot00000000000000 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.2.0+dfsg/wrappers/csharp/src/test/KinectDemo/openkinect_logo.png000066400000000000000000000137521221743053000275170ustar00rootroot00000000000000PNG  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