--- /dev/null
+.project
+.cproject
+
+aclocal.m4
+autom4te.cache
+config.guess
+config.log
+config.status
+config.sub
+depcomp
+configure
+install-sh
+INSTALL
+libtool
+ltmain.sh
+Makefile
+Makefile.in
+missing
+
+libcec.dll
+libcec.exp
+libcec.ilk
+libcec.lib
+libcec.pdb
+testclient.exe
+testclient.ilk
+testclient.pdb
+
+project/Debug/
+project/ipch/
+project/libcec.sdf
+project/libcec.suo
+project/libcec.vcxproj.user
+project/testclient.vcxproj.user
+
+src/lib/.deps
+src/lib/.libs
+src/lib/*.a
+src/lib/*.la
+src/lib/*.lo
+src/lib/*.o
+src/lib/*.P
+src/lib/libcec.pc
+src/lib/Makefile
+src/lib/Makefile.in
+
+src/lib/util/*.d
+src/lib/util/*.o
+src/lib/util/*.a
+src/lib/util/*.P
+
+src/testclient/.deps
+src/testclient/.libs
+src/testclient/cec-client
+src/testclient/*.o
+
--- /dev/null
+Lars Op den Kamp <lars.opdenkamp@pulse-eight.com>
+Bob van Loosen <bob.loosen@gmail.com>
+Martin Ellis <martin.ellis@pulse-eight.com>
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is a original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+libcec (0.1-1) unstable; urgency=low
+
+ * Initial release v0.1
+
+ -- Lars Op den Kamp <info@pulse-eight.com> Wed, 28 Sep 2011 21:42:48 +0200
--- /dev/null
+SUBDIRS = src/lib src/testclient
\ No newline at end of file
--- /dev/null
+For Linux:
+autoreconf -vif
+./configure --prefix=/usr
+make
+sudo make install
+
+For Windows:
+Open /project/libcec.sln with Visual C++ 2010 or Visual Studio 2010.
+Build the project.
+Copy libcec.dll and libpthread.dll to your desired destination.
+
+Test the device:
+Run "cec-client -h" to display the options of the test client.
+
+For developers:
+See /include/CECExports.h
--- /dev/null
+AC_INIT([libcec], 0:1:0)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+AC_CHECK_LIB([rt], [main],, AC_MSG_ERROR("required library 'rt' is missing"))
+AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR("required library 'pthread' is missing"))
+AC_CHECK_LIB([udev], [main],, AC_MSG_ERROR("required library 'udev' is missing"))
+
+AC_CONFIG_FILES([src/lib/libcec.pc])
+AC_OUTPUT([Makefile src/lib/Makefile src/testclient/Makefile])
\ No newline at end of file
--- /dev/null
+libcec (0.1-1) unstable; urgency=low
+
+ * Initial release v0.1
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Wed, 28 Sep 2011 23:55:48 +0200
--- /dev/null
+Source: libcec
+Section: video
+Priority: extra
+Maintainer: Lars Op den Kamp <info@pulse-eight.com>
+Build-Depends: debhelper (>= 7), libudev-dev, mime-support,
+ locales, gawk, autotools-dev, autoconf, automake,
+Standards-Version: 3.8.3
+Homepage: http://www.pulse-eight.net/
+
+Package: libcec
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: CEC interface library
+ CEC interface library.
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is a original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+README
+COPYING
+AUTHORS
+ChangeLog
--- /dev/null
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+export DH_VERBOSE=1
+
+%:
+ dh $@
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#ifndef CECEXPORTS_H_
+#define CECEXPORTS_H_
+
+#include <string>
+#include <stdint.h>
+#include <vector>
+
+#if !defined(DECLSPEC)
+#if defined(_WIN32) || defined(_WIN64)
+#include <windows.h>
+#if defined DLL_EXPORT
+#define DECLSPEC __declspec(dllexport)
+#else
+#define DECLSPEC __declspec(dllimport)
+#endif
+#else
+#define DECLSPEC
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+namespace CEC {
+#endif
+ #define CEC_MIN_VERSION 1
+ #define CEC_LIB_VERSION 1
+ #define CEC_SETTLE_DOWN_TIME 1000
+
+ typedef std::vector<uint8_t> cec_frame;
+
+ typedef enum cec_user_control_code
+ {
+ CEC_USER_CONTROL_CODE_SELECT = 0x00,
+ CEC_USER_CONTROL_CODE_UP = 0x01,
+ CEC_USER_CONTROL_CODE_DOWN = 0x02,
+ CEC_USER_CONTROL_CODE_LEFT = 0x03,
+ CEC_USER_CONTROL_CODE_RIGHT = 0x04,
+ CEC_USER_CONTROL_CODE_RIGHT_UP = 0x05,
+ CEC_USER_CONTROL_CODE_RIGHT_DOWN = 0x06,
+ CEC_USER_CONTROL_CODE_LEFT_UP = 0x07,
+ CEC_USER_CONTROL_CODE_LEFT_DOWN = 0x08,
+ CEC_USER_CONTROL_CODE_ROOT_MENU = 0x09,
+ CEC_USER_CONTROL_CODE_SETUP_MENU = 0x0A,
+ CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B,
+ CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C,
+ CEC_USER_CONTROL_CODE_EXIT = 0x0D,
+ CEC_USER_CONTROL_CODE_NUMBER0 = 0x20,
+ CEC_USER_CONTROL_CODE_NUMBER1 = 0x21,
+ CEC_USER_CONTROL_CODE_NUMBER2 = 0x22,
+ CEC_USER_CONTROL_CODE_NUMBER3 = 0x23,
+ CEC_USER_CONTROL_CODE_NUMBER4 = 0x24,
+ CEC_USER_CONTROL_CODE_NUMBER5 = 0x25,
+ CEC_USER_CONTROL_CODE_NUMBER6 = 0x26,
+ CEC_USER_CONTROL_CODE_NUMBER7 = 0x27,
+ CEC_USER_CONTROL_CODE_NUMBER8 = 0x28,
+ CEC_USER_CONTROL_CODE_NUMBER9 = 0x29,
+ CEC_USER_CONTROL_CODE_DOT = 0x2A,
+ CEC_USER_CONTROL_CODE_ENTER = 0x2B,
+ CEC_USER_CONTROL_CODE_CLEAR = 0x2C,
+ CEC_USER_CONTROL_CODE_NEXT_FAVORITE = 0x2F,
+ CEC_USER_CONTROL_CODE_CHANNEL_UP = 0x30,
+ CEC_USER_CONTROL_CODE_CHANNEL_DOWN = 0x31,
+ CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL = 0x32,
+ CEC_USER_CONTROL_CODE_SOUND_SELECT = 0x33,
+ CEC_USER_CONTROL_CODE_INPUT_SELECT = 0x34,
+ CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION = 0x35,
+ CEC_USER_CONTROL_CODE_HELP = 0x36,
+ CEC_USER_CONTROL_CODE_PAGE_UP = 0x37,
+ CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38,
+ CEC_USER_CONTROL_CODE_POWER = 0x40,
+ CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41,
+ CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42,
+ CEC_USER_CONTROL_CODE_MUTE = 0x43,
+ CEC_USER_CONTROL_CODE_PLAY = 0x44,
+ CEC_USER_CONTROL_CODE_STOP = 0x45,
+ CEC_USER_CONTROL_CODE_PAUSE = 0x46,
+ CEC_USER_CONTROL_CODE_RECORD = 0x47,
+ CEC_USER_CONTROL_CODE_REWIND = 0x48,
+ CEC_USER_CONTROL_CODE_FAST_FORWARD = 0x49,
+ CEC_USER_CONTROL_CODE_EJECT = 0x4A,
+ CEC_USER_CONTROL_CODE_FORWARD = 0x4B,
+ CEC_USER_CONTROL_CODE_BACKWARD = 0x4C,
+ CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D,
+ CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E,
+ CEC_USER_CONTROL_CODE_ANGLE = 0x50,
+ CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51,
+ CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52,
+ CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53,
+ CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54,
+ CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55,
+ CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60,
+ CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61,
+ CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62,
+ CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION = 0x63,
+ CEC_USER_CONTROL_CODE_STOP_FUNCTION = 0x64,
+ CEC_USER_CONTROL_CODE_MUTE_FUNCTION = 0x65,
+ CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION = 0x66,
+ CEC_USER_CONTROL_CODE_TUNE_FUNCTION = 0x67,
+ CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION = 0x68,
+ CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION = 0x69,
+ CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A,
+ CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B,
+ CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C,
+ CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D,
+ CEC_USER_CONTROL_CODE_F1_BLUE = 0x71,
+ CEC_USER_CONTROL_CODE_F2_RED = 0X72,
+ CEC_USER_CONTROL_CODE_F3_GREEN = 0x73,
+ CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74,
+ CEC_USER_CONTROL_CODE_F5 = 0x75,
+ CEC_USER_CONTROL_CODE_DATA = 0x76,
+ CEC_USER_CONTROL_CODE_MAX = 0x76,
+ CEC_USER_CONTROL_CODE_UNKNOWN
+ } cec_user_control_code;
+
+ typedef enum cec_logical_address
+ {
+ CECDEVICE_UNKNOWN = -1, //not a valid logical address
+ CECDEVICE_TV,
+ CECDEVICE_RECORDINGDEVICE1,
+ CECDEVICE_RECORDINGDEVICE2,
+ CECDEVICE_TUNER1,
+ CECDEVICE_PLAYBACKDEVICE1,
+ CECDEVICE_AUDIOSYSTEM,
+ CECDEVICE_TUNER2,
+ CECDEVICE_TUNER3,
+ CECDEVICE_PLAYBACKDEVICE2,
+ CECDEVICE_RECORDINGDEVICE3,
+ CECDEVICE_TUNER4,
+ CECDEVICE_PLAYBACKDEVICE3,
+ CECDEVICE_RESERVED1,
+ CECDEVICE_RESERVED2,
+ CECDEVICE_FREEUSE,
+ CECDEVICE_UNREGISTERED = 15,
+ CECDEVICE_BROADCAST = 15
+ } cec_logical_address;
+
+ typedef enum cec_log_level
+ {
+ CEC_LOG_DEBUG = 0,
+ CEC_LOG_NOTICE,
+ CEC_LOG_WARNING,
+ CEC_LOG_ERROR
+ } cec_log_level;
+
+ typedef struct cec_log_message
+ {
+ std::string message;
+ cec_log_level level;
+ } cec_log_message;
+
+ typedef struct cec_keypress
+ {
+ cec_user_control_code keycode;
+ unsigned int duration;
+ } cec_keypress;
+
+ typedef struct cec_device
+ {
+ std::string path;
+ std::string comm;
+ } cec_device;
+};
+
+#ifdef __cplusplus
+#include "CECExportsCpp.h"
+#include "CECExportsC.h"
+};
+#else
+#include "CECExportsC.h"
+#endif
+
+#endif /* CECEXPORTS_H_ */
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#ifndef CECEXPORTS_C_H_
+#define CECEXPORTS_C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @brief Initialise the cec device.
+ * @param strDeviceName How to present this device to other devices.
+ * @return True when initialised, false otherwise.
+ */
+extern DECLSPEC bool cec_init(const char *strDeviceName);
+
+/*!
+ * @brief Close the cec device.
+ * @return True when the device was closed, false otherwise.
+ */
+extern DECLSPEC bool cec_close(void);
+
+/*!
+ * @brief Open a connection to the CEC adapter.
+ * @param strPort The path to the port.
+ * @param iTimeout Connection timeout in ms.
+ * @return True when connected, false otherwise.
+ */
+extern DECLSPEC bool cec_open(const char *strPort, int iTimeout);
+
+/*!
+ * @brief Ping the CEC adapter.
+ * @return True when the ping was succesful, false otherwise.
+ */
+extern DECLSPEC bool cec_ping(void);
+
+/*!
+ * @brief Start the bootloader of the CEC adapter.
+ * @return True when the command was sent succesfully, false otherwise.
+ */
+extern DECLSPEC bool cec_start_bootloader(void);
+
+/*!
+ * @brief Power off connected CEC capable devices.
+ * @return True when the command was sent succesfully, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC bool cec_power_off_devices(CEC::cec_logical_address address = CEC::CECDEVICE_BROADCAST);
+#else
+extern DECLSPEC bool cec_power_off_devices(cec_logical_address address = CECDEVICE_BROADCAST);
+#endif
+
+/*!
+ * @brief Power on the connected CEC capable devices.
+ * @return True when the command was sent succesfully, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC bool cec_power_on_devices(CEC::cec_logical_address address = CEC::CECDEVICE_BROADCAST);
+#else
+extern DECLSPEC bool cec_power_on_devices(cec_logical_address address = CECDEVICE_BROADCAST);
+#endif
+
+/*!
+ * @brief Put connected CEC capable devices in standby mode.
+ * @return True when the command was sent succesfully, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC bool cec_standby_devices(CEC::cec_logical_address address = CEC::CECDEVICE_BROADCAST);
+#else
+extern DECLSPEC bool cec_standby_devices(cec_logical_address address = CECDEVICE_BROADCAST);
+#endif
+
+/*!
+ * @brief Set this device as the active source on connected CEC capable devices.
+ * @return True when the command was sent succesfully, false otherwise.
+ */
+extern DECLSPEC bool cec_set_active_view(void);
+
+/*!
+ * @brief Mark this device as inactive on connected CEC capable devices.
+ * @return True when the command was sent succesfully, false otherwise.
+ */
+extern DECLSPEC bool cec_set_inactive_view(void);
+
+/*!
+ * @brief Get the next log message in the queue, if there is one.
+ * @param message The next message.
+ * @return True if a message was passed, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC bool cec_get_next_log_message(CEC::cec_log_message *message);
+#else
+extern DECLSPEC bool cec_get_next_log_message(cec_log_message *message);
+#endif
+
+/*!
+ * @brief Get the next keypress in the queue, if there is one.
+ * @param key The next keypress
+ * @return True if a key was passed, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC bool cec_get_next_keypress(CEC::cec_keypress *key);
+#else
+extern DECLSPEC bool cec_get_next_keypress(cec_keypress *key);
+#endif
+
+/*!
+ * @brief Transmit a frame and wait for ACK.
+ * @param data The frame to send.
+ * @return True when the data was sent and acked, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC bool cec_transmit(const CEC::cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 5000);
+#else
+extern DECLSPEC bool cec_transmit(const cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 5000);
+#endif
+
+/*!
+ * @brief Set the ack mask for the CEC adapter.
+ * @param ackmask The new ack mask.
+ * @return True when the ack mask was sent succesfully, false otherwise.
+ */
+extern DECLSPEC bool cec_set_ack_mask(uint16_t ackmask);
+
+extern DECLSPEC int cec_get_min_version(void);
+extern DECLSPEC int cec_get_lib_version(void);
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_find_devices(std::vector<CEC::cec_device> &deviceList, const char *strDevicePath = NULL);
+#else
+extern DECLSPEC int cec_find_devices(std::vector<cec_device> &deviceList, const char *strDevicePath = NULL);
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* CECEXPORTS_C_H_ */
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+namespace CEC
+{
+ class ICECDevice
+ {
+ public:
+ /*!
+ * @see cec_open
+ */
+ virtual bool Open(const char *strPort, int iTimeoutMs = 10000) = 0;
+
+ /*!
+ * @see cec_find_devices
+ */
+ virtual int FindDevices(std::vector<cec_device> &deviceList, const char *strDevicePath = NULL) = 0;
+
+ /*!
+ * @see cec_ping
+ */
+ virtual bool Ping(void) = 0;
+
+ /*!
+ * @see cec_start_bootloader
+ */
+ virtual bool StartBootloader(void) = 0;
+
+ /*!
+ * @see cec_power_off_devices
+ */
+ virtual bool PowerOffDevices(cec_logical_address address = CECDEVICE_BROADCAST) = 0;
+
+ /*!
+ * @see cec_power_on_devices
+ */
+ virtual bool PowerOnDevices(cec_logical_address address = CECDEVICE_BROADCAST) = 0;
+
+ /*!
+ * @see cec_standby_devices
+ */
+ virtual bool StandbyDevices(cec_logical_address address = CECDEVICE_BROADCAST) = 0;
+
+ /*!
+ * @see cec_set_active_view
+ */
+ virtual bool SetActiveView(void) = 0;
+
+ /*!
+ * @see cec_set_inactive_view
+ */
+ virtual bool SetInactiveView(void) = 0;
+
+ /*!
+ * @see cec_get_next_log_message
+ */
+ virtual bool GetNextLogMessage(cec_log_message *message) = 0;
+
+ /*!
+ * @see cec_get_next_keypress
+ */
+ virtual bool GetNextKeypress(cec_keypress *key) = 0;
+
+ /*!
+ * @see cec_transmit
+ */
+ virtual bool Transmit(const cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 5000) = 0;
+
+ /*!
+ * @see cec_set_ack_mask
+ */
+ virtual bool SetAckMask(cec_logical_address ackmask) = 0;
+
+ virtual int GetMinVersion(void) = 0;
+ virtual int GetLibVersion(void) = 0;
+ };
+};
+
+extern DECLSPEC void * CECCreate(const char *strDeviceName);
+
+#if !defined(DLL_EXPORT)
+#if defined(_WIN32) || defined(_WIN64)
+#include <windows.h>
+#include <conio.h>
+
+static HINSTANCE g_libCEC = NULL;
+inline CEC::ICECDevice *LoadLibCec(const char *strName)
+{
+ typedef void* (__cdecl*_CreateLibCec)(const char *);
+ _CreateLibCec CreateLibCec;
+
+ g_libCEC = LoadLibrary("libcec.dll");
+ if (!g_libCEC)
+ return NULL;
+ CreateLibCec = (_CreateLibCec) (GetProcAddress(g_libCEC, "CECCreate"));
+ if (!CreateLibCec)
+ return NULL;
+ return static_cast< CEC::ICECDevice* > (CreateLibCec(strName));
+}
+
+inline void UnloadLibCec(CEC::ICECDevice *device)
+{
+ delete device;
+ FreeLibrary(g_libCEC);
+};
+
+#else
+inline CEC::ICECDevice *LoadLibCec(const char *strName)
+{
+ return (CEC::ICECDevice*) CECCreate(strName);
+};
+
+inline void UnloadLibCec(CEC::ICECDevice *device)
+{
+ delete device;
+};
+#endif
+
+#endif
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include <stdint.h>
+#include <vector>
+#include <string>
+#include "CECExports.h"
+
+typedef enum
+{
+ CEC_OPCODE_ACTIVE_SOURCE = 0x82,
+ CEC_OPCODE_IMAGE_VIEW_ON = 0x04,
+ CEC_OPCODE_TEXT_VIEW_ON = 0x0D,
+ CEC_OPCODE_INACTIVE_SOURCE = 0x9D,
+ CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85,
+ CEC_OPCODE_ROUTING_CHANGE = 0x80,
+ CEC_OPCODE_ROUTING_INFORMATION = 0x81,
+ CEC_OPCODE_SET_STREAM_PATH = 0x86,
+ CEC_OPCODE_STANDBY = 0x36,
+ CEC_OPCODE_RECORD_OFF = 0x0B,
+ CEC_OPCODE_RECORD_ON = 0x09,
+ CEC_OPCODE_RECORD_STATUS = 0x0A,
+ CEC_OPCODE_RECORD_TV_SCREEN = 0x0F,
+ CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33,
+ CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99,
+ CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1,
+ CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34,
+ CEC_OPCODE_SET_DIGITAL_TIMER = 0x97,
+ CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2,
+ CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67,
+ CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43,
+ CEC_OPCODE_TIMER_STATUS = 0x35,
+ CEC_OPCODE_CEC_VERSION = 0x9E,
+ CEC_OPCODE_GET_CEC_VERSION = 0x9F,
+ CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83,
+ CEC_OPCODE_GET_MENU_LANGUAGE = 0x91,
+ CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84,
+ CEC_OPCODE_SET_MENU_LANGUAGE = 0x32,
+ CEC_OPCODE_DECK_CONTROL = 0x42,
+ CEC_OPCODE_DECK_STATUS = 0x1B,
+ CEC_OPCODE_GIVE_DECK_STATUS = 0x1A,
+ CEC_OPCODE_PLAY = 0x41,
+ CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08,
+ CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92,
+ CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93,
+ CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07,
+ CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06,
+ CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05,
+ CEC_OPCODE_DEVICE_VENDOR_ID = 0x87,
+ CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C,
+ CEC_OPCODE_VENDOR_COMMAND = 0x89,
+ CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0,
+ CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+ CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B,
+ CEC_OPCODE_SET_OSD_STRING = 0x64,
+ CEC_OPCODE_GIVE_OSD_NAME = 0x46,
+ CEC_OPCODE_SET_OSD_NAME = 0x47,
+ CEC_OPCODE_MENU_REQUEST = 0x8D,
+ CEC_OPCODE_MENU_STATUS = 0x8E,
+ CEC_OPCODE_USER_CONTROL_PRESSED = 0x44,
+ CEC_OPCODE_USER_CONTROL_RELEASE = 0x45,
+ CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F,
+ CEC_OPCODE_REPORT_POWER_STATUS = 0x90,
+ CEC_OPCODE_FEATURE_ABORT = 0x00,
+ CEC_OPCODE_ABORT = 0xFF,
+ CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71,
+ CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
+ CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A,
+ CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72,
+ CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70,
+ CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E,
+ CEC_OPCODE_SET_AUDIO_RATE = 0x9A
+} ECecOpcode;
+
+typedef enum
+{
+ CEC_ABORT_REASON_UNRECOGNIZED_OPCODE = 0,
+ CEC_ABORT_REASON_NOT_IN_CORRECT_MODE_TO_RESPOND = 1,
+ CEC_ABORT_REASON_CANNOT_PROVIDE_SOURCE = 2,
+ CEC_ABORT_REASON_INVALID_OPERAND = 3,
+ CEC_ABORT_REASON_REFUSED = 4
+} ECecAbortReason;
+
+typedef enum
+{
+ CEC_ANALOGUE_BROADCAST_TYPE_CABLE = 0x00,
+ CEC_ANALOGUE_BROADCAST_TYPE_SATELLITE = 0x01,
+ CEC_ANALOGUE_BROADCAST_TYPE_TERRESTIAL = 0x02
+} ECecAnalogueBroadcastType;
+
+typedef enum
+{
+ CEC_AUDIO_RATE_RATE_CONTROL_OFF = 0,
+ CEC_AUDIO_RATE_STANDARD_RATE_100 = 1,
+ CEC_AUDIO_RATE_FAST_RATE_MAX_101 = 2,
+ CEC_AUDIO_RATE_SLOW_RATE_MIN_99 = 3,
+ CEC_AUDIO_RATE_STANDARD_RATE_100_0 = 4,
+ CEC_AUDIO_RATE_FAST_RATE_MAX_100_1 = 5,
+ CEC_AUDIO_RATE_SLOW_RATE_MIN_99_9 = 6
+} ECecAudioRate;
+
+typedef enum
+{
+ CEC_AUDIO_MUTE_STATUS_MASK = 0x80,
+ CEC_AUDIO_VOLUME_STATUS_MASK = 0x7F,
+ CEC_AUDIO_VOLUME_MIN = 0x00,
+ CEC_AUDIO_VOLUME_MAX = 0x64,
+ CEC_AUDIO_VOLUME_STATUS_UNKNOWN = 0x7F
+} ECecAudioStatus;
+
+typedef enum
+{
+ CEC_FALSE = 0,
+ CEC_TRUE = 1
+} ECecBoolean;
+
+typedef enum
+{
+ CEC_VERSION_1_2 = 0x01,
+ CEC_VERSION_1_2A = 0x02,
+ CEC_VERSION_1_3 = 0x03,
+ CEC_VERSION_1_3A = 0x04
+} ECecVersion;
+
+typedef enum
+{
+ CEC_CHANNEL_NUMBER_FORMAT_MASK = 0xFC000000,
+ CEC_1_PART_CHANNEL_NUMBER = 0x04000000,
+ CEC_2_PART_CHANNEL_NUMBER = 0x08000000,
+ CEC_MAJOR_CHANNEL_NUMBER_MASK = 0x3FF0000,
+ CEC_MINOR_CHANNEL_NUMBER_MASK = 0xFFFF
+} ECecChannelIdentifier;
+
+typedef enum
+{
+ CEC_DESK_CONTROL_MODE_SKIP_FORWARD_WIND = 1,
+ CEC_DESK_CONTROL_MODE_SKIP_REVERSE_REWIND = 2,
+ CEC_DESK_CONTROL_MODE_STOP = 3,
+ CEC_DESK_CONTROL_MODE_EJECT = 4
+} ECecDeskControlMode;
+
+typedef enum
+{
+ CEC_DECK_INFO_PLAY = 0x11,
+ CEC_DECK_INFO_RECORD = 0x12,
+ CEC_DECK_INFO_PLAY_REVERSE = 0x13,
+ CEC_DECK_INFO_STILL = 0x14,
+ CEC_DECK_INFO_SLOW = 0x15,
+ CEC_DECK_INFO_SLOW_REVERSE = 0x16,
+ CEC_DECK_INFO_FAST_FORWARD = 0x17,
+ CEC_DECK_INFO_FAST_REVERSE = 0x18,
+ CEC_DECK_INFO_NO_MEDIA = 0x19,
+ CEC_DECK_INFO_STOP = 0x1A,
+ CEC_DECK_INFO_SKIP_FORWARD_WIND = 0x1B,
+ CEC_DECK_INFO_SKIP_REVERSE_REWIND = 0x1C,
+ CEC_DECK_INFO_INDEX_SEARCH_FORWARD = 0x1D,
+ CEC_DECK_INFO_INDEX_SEARCH_REVERSE = 0x1E,
+ CEC_DECK_INFO_OTHER_STATUS = 0x1F
+} ECecDeckInfo;
+
+typedef enum
+{
+ CEC_DEVICE_TYPE_TV = 0,
+ CEC_DEVICE_TYPE_RECORDING_DEVICE = 1,
+ CEC_DEVICE_TYPE_RESERVED = 2,
+ CEC_DEVICE_TYPE_TUNER = 3,
+ CEC_DEVICE_TYPE_PLAYBACK_DEVICE = 4,
+ CEC_DEVICE_TYPE_AUDIO_SYSTEM = 5
+} ECecDeviceType;
+
+typedef enum
+{
+ CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME = 0x00,
+ CEC_DISPLAY_CONTROL_DISPLAY_UNTIL_CLEARED = 0x40,
+ CEC_DISPLAY_CONTROL_CLEAR_PREVIOUS_MESSAGE = 0x80,
+ CEC_DISPLAY_CONTROL_RESERVED_FOR_FUTURE_USE = 0xC0
+} ECecDisplayControl;
+
+typedef enum
+{
+ CEC_EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG = 4,
+ CEC_EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS = 5
+} ECecExternalSourceSpecifier;
+
+typedef enum
+{
+ CEC_MENU_REQUEST_TYPE_ACTIVATE = 0,
+ CEC_MENU_REQUEST_TYPE_DEACTIVATE = 1,
+ CEC_MENU_REQUEST_TYPE_QUERY = 2
+} ECecMenuRequestType;
+
+typedef enum
+{
+ CEC_MENU_STATE_ACTIVATED = 0,
+ CEC_MENU_STATE_DEACTIVATED = 1
+} ECecMenuState;
+
+typedef enum
+{
+ CEC_PLAY_MODE_PLAY_FORWARD = 0x24,
+ CEC_PLAY_MODE_PLAY_REVERSE = 0x20,
+ CEC_PLAY_MODE_PLAY_STILL = 0x25,
+ CEC_PLAY_MODE_FAST_FORWARD_MIN_SPEED = 0x05,
+ CEC_PLAY_MODE_FAST_FORWARD_MEDIUM_SPEED = 0x06,
+ CEC_PLAY_MODE_FAST_FORWARD_MAX_SPEED = 0x07,
+ CEC_PLAY_MODE_FAST_REVERSE_MIN_SPEED = 0x09,
+ CEC_PLAY_MODE_FAST_REVERSE_MEDIUM_SPEED = 0x0A,
+ CEC_PLAY_MODE_FAST_REVERSE_MAX_SPEED = 0x0B,
+ CEC_PLAY_MODE_SLOW_FORWARD_MIN_SPEED = 0x15,
+ CEC_PLAY_MODE_SLOW_FORWARD_MEDIUM_SPEED = 0x16,
+ CEC_PLAY_MODE_SLOW_FORWARD_MAX_SPEED = 0x17,
+ CEC_PLAY_MODE_SLOW_REVERSE_MIN_SPEED = 0x19,
+ CEC_PLAY_MODE_SLOW_REVERSE_MEDIUM_SPEED = 0x1A,
+ CEC_PLAY_MODE_SLOW_REVERSE_MAX_SPEED = 0x1B
+} ECecPlayMode;
+
+typedef enum
+{
+ CEC_POWER_STATUS_ON = 0x00,
+ CEC_POWER_STATUS_STANDBY = 0x01,
+ CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON = 0x02,
+ CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY = 0x03
+} ECecPowerStatus;
+
+typedef enum
+{
+ CEC_RECORD_SOURCE_TYPE_OWN_SOURCE = 1,
+ CEC_RECORD_SOURCE_TYPE_DIGITAL_SERVICE = 2,
+ CEC_RECORD_SOURCE_TYPE_ANALOGUE_SERVICE = 3,
+ CEC_RECORD_SOURCE_TYPE_EXTERNAL_PLUS = 4,
+ CEC_RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 5
+} ECecRecordSourceType;
+
+typedef enum
+{
+ CEC_RECORD_STATUS_INFO_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01,
+ CEC_RECORD_STATUS_INFO_RECORDING_DIGITAL_SERVICE = 0x02,
+ CEC_RECORD_STATUS_INFO_RECORDING_ANALOGUE_SERVICE = 0x03,
+ CEC_RECORD_STATUS_INFO_RECORDING_EXTERNAL_INPUT = 0x04,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_RECORD_DIGITAL_SERVICE = 0x05,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_RECORD_ANALOGUE_SERVICE = 0x06,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_SELECT_REQUIRED_SERVICE = 0x07,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_INVALID_EXTERNAL_PLUG_NUMBER = 0x09,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_INVALID_EXTERNAL_ADDRESS = 0x0A,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_CA_SYSTEM_NOT_SUPPORTED = 0x0B,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_OR_INSUFFICIENT_ENTITLEMENTS = 0x0C,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NOT_ALLOWED_TO_COPY_SOURCE = 0x0D,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_FURTHER_COPIES_ALLOWED = 0x0E,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_MEDIA = 0x10,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_PLAYING = 0x11,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_ALREADY_RECORDING = 0x12,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_MEDIA_PROTECTED = 0x13,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_SOURCE_SIGNAL = 0x14,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_MEDIA_PROBLEM = 0x15,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NOT_ENOUGH_SPACE_AVAILABLE = 0x16,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_PARENTAL_LOCK_ON = 0x17,
+ CEC_RECORD_STATUS_INFO_RECORDING_TERMINATED_NORMALLY = 0x1A,
+ CEC_RECORD_STATUS_INFO_RECORDING_HAS_ALREADY_TERMINATED = 0x1B,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_OTHER_REASON = 0x1F
+} ECecRecordStatusInfo;
+
+typedef enum
+{
+ CEC_RECORDING_SEQUENCE_SUNDAY = 0x01,
+ CEC_RECORDING_SEQUENCE_MONDAY = 0x02,
+ CEC_RECORDING_SEQUENCE_TUESDAY = 0x04,
+ CEC_RECORDING_SEQUENCE_WEDNESDAY = 0x08,
+ CEC_RECORDING_SEQUENCE_THURSDAY = 0x10,
+ CEC_RECORDING_SEQUENCE_FRIDAY = 0x20,
+ CEC_RECORDING_SEQUENCE_SATURDAY = 0x40,
+ CEC_RECORDING_SEQUENCE_ONCE_ONLY = 0x00
+} ECecRecordingSequence;
+
+typedef enum
+{
+ CEC_STATUS_REQUEST_ON = 1,
+ CEC_STATUS_REQUEST_OFF = 2,
+ CEC_STATUS_REQUEST_ONCE = 3
+} ECecStatusRequest;
+
+typedef enum
+{
+ CEC_SYSTEM_AUDIO_STATUS_OFF = 0,
+ CEC_SYSTEM_AUDIO_STATUS_ON = 1
+} ECecSystemAudioStatus;
+
+typedef enum
+{
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_RECORDING = 0x00,
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_NO_MATCHING = 0x01,
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_NO_INF0_AVAILABLE = 0x02,
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_CLEARED = 0x80
+} ECecTimerClearedStatusData;
+
+typedef enum
+{
+ CEC_TIMER_OVERLAP_WARNING_NO_OVERLAP = 0,
+ CEC_TIMER_OVERLAP_WARNING_TIMER_BLOCKS_OVERLAP = 1
+} ECecTimerOverlapWarning;
+
+typedef enum
+{
+ CEC_MEDIA_INFO_MEDIA_PRESENT_AND_NOT_PROTECTED = 0x00,
+ CEC_MEDIA_INFO_MEDIA_PRESENT_BUT_PROTECTED = 0x01,
+ CEC_MEDIA_INFO_MEDIA_NOT_PRESENT = 0x02,
+ CEC_MEDIA_INFO_FUTURE_USE = 0x03
+} ECecMediaInfo;
+
+typedef enum
+{
+ CEC_PROGRAMMED_INDICATOR_NOT_PROGRAMMED = 0,
+ CEC_PROGRAMMED_INDICATOR_PROGRAMMED = 1
+} ECecProgrammedIndicator;
+
+typedef enum
+{
+ CEC_PROGRAMMED_INFO_FUTURE_USE = 0x0,
+ CEC_PROGRAMMED_INFO_ENOUGH_SPACE_AVAILABLE_FOR_RECORDING = 0x08,
+ CEC_PROGRAMMED_INFO_NOT_ENOUGH_SPACE_AVAILABLE_FOR_RECORDING = 0x09,
+ CEC_PROGRAMMED_INFO_MAY_NOT_BE_ENOUGH_SPACE_AVAILABLE = 0x0B,
+ CEC_PROGRAMMED_INFO_NO_MEDIA_INFO_AVAILABLE = 0x0A
+} ECecProgrammedInfo;
+
+typedef enum
+{
+ CEC_NOT_PROGRAMMED_ERROR_INFO_FUTURE_USE = 0x0,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_NO_FREE_TIMER_AVAILABLE = 0x01,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_DATE_OUT_OF_RANGE = 0x02,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_RECORDING_SEQUENCE_ERROR = 0x03,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_INVALID_EXTERNAL_PLUG_NUMBER = 0x04,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x05,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_CA_SYSTEM_NOT_SUPPORTED = 0x06,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x07,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_DOES_NOT_SUPPORT_RESOLUTION = 0x08,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_PARENTAL_LOCK_ON = 0x09,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_CLOCK_FAILURE = 0x0A,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_RESERVED_FOR_FUTURE_USE_START = 0x0B,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_RESERVED_FOR_FUTURE_USE_END = 0x0D,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED = 0x0E
+} ECecNotProgrammedErrorInfo;
+
+typedef enum
+{
+ CEC_RECORDING_FLAG_NOT_BEING_USED_FOR_RECORDING = 0,
+ CEC_RECORDING_FLAG_BEING_USED_FOR_RECORDING = 1
+} ECecRecordingFlag;
+
+typedef enum
+{
+ CEC_TUNER_DISPLAY_INFO_DISPLAYING_DIGITAL_TUNER = 0,
+ CEC_TUNER_DISPLAY_INFO_NOT_DISPLAYING_TUNER = 1,
+ CEC_TUNER_DISPLAY_INFO_DISPLAYING_ANALOGUE_TUNER = 2
+} ECecTunerDisplayInfo;
+
+
+typedef enum
+{
+ CEC_BROADCAST_SYSTEM_PAL_B_G = 0,
+ CEC_BROADCAST_SYSTEM_SECAM_L1 = 1,
+ CEC_BROADCAST_SYSTEM_PAL_M = 2,
+ CEC_BROADCAST_SYSTEM_NTSC_M = 3,
+ CEC_BROADCAST_SYSTEM_PAL_I = 4,
+ CEC_BROADCAST_SYSTEM_SECAM_DK = 5,
+ CEC_BROADCAST_SYSTEM_SECAM_B_G = 6,
+ CEC_BROADCAST_SYSTEM_SECAM_L2 = 7,
+ CEC_BROADCAST_SYSTEM_PAL_DK = 8,
+ CEC_BROADCAST_SYSTEM_OTHER_SYSTEM = 30
+} ECecBroadcastSystem;
+
+typedef enum
+{
+ MSGCODE_NOTHING = 0,
+ MSGCODE_PING,
+ MSGCODE_TIMEOUT_ERROR,
+ MSGCODE_HIGH_ERROR,
+ MSGCODE_LOW_ERROR,
+ MSGCODE_FRAME_START,
+ MSGCODE_FRAME_DATA,
+ MSGCODE_RECEIVE_FAILED,
+ MSGCODE_COMMAND_ACCEPTED,
+ MSGCODE_COMMAND_REJECTED,
+ MSGCODE_SET_ACK_MASK,
+ MSGCODE_TRANSMIT,
+ MSGCODE_TRANSMIT_EOM,
+ MSGCODE_TRANSMIT_IDLETIME,
+ MSGCODE_TRANSMIT_ACK_POLARITY,
+ MSGCODE_TRANSMIT_LINE_TIMEOUT,
+ MSGCODE_TRANSMIT_SUCCEEDED,
+ MSGCODE_TRANSMIT_FAILED_LINE,
+ MSGCODE_TRANSMIT_FAILED_ACK,
+ MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
+ MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
+ MSGCODE_FIRMWARE_VERSION,
+ MSGCODE_START_BOOTLOADER,
+ MSGCODE_FRAME_EOM = 0x80,
+ MSGCODE_FRAME_ACK = 0x40,
+} ECecMessageCode;
+
+//default physical address 1.0.0.0
+#define CEC_DEFAULT_PHYSICAL_ADDRESS 0x1000
+#define MSGSTART 0xFF
+#define MSGEND 0xFE
+#define MSGESC 0xFD
+#define ESCOFFSET 3
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\tools.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\client.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\HTSPData.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\HTSPDemux.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\thread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\addons\library.xbmc.addon\dlfcn-win32.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\HTSPConnection.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\..\addons\library.xbmc.addon\dlfcn-win32.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\thread.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tools.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\client.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\HTSPData.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\HTSPDemux.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\HTSPConnection.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcec", "libcec.vcxproj", "{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testclient", "testclient.vcxproj", "{F01222BF-6B3D-43BD-B254-434031CB9887}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0} = {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Win32.Build.0 = Debug|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Win32.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\CECExports.h" />
+ <ClInclude Include="..\include\CECExportsC.h" />
+ <ClInclude Include="..\include\CECExportsCpp.h" />
+ <ClInclude Include="..\include\CECTypes.h" />
+ <ClInclude Include="..\src\lib\CECDetect.h" />
+ <ClInclude Include="..\src\lib\CECParser.h" />
+ <ClInclude Include="..\src\lib\libPlatform\baudrate.h" />
+ <ClInclude Include="..\src\lib\libPlatform\os-dependent.h" />
+ <ClInclude Include="..\src\lib\libPlatform\pthread_win32\pthread.h" />
+ <ClInclude Include="..\src\lib\libPlatform\pthread_win32\sched.h" />
+ <ClInclude Include="..\src\lib\libPlatform\pthread_win32\semaphore.h" />
+ <ClInclude Include="..\src\lib\libPlatform\serialport.h" />
+ <ClInclude Include="..\src\lib\libPlatform\windows\dlfcn-win32.h" />
+ <ClInclude Include="..\src\lib\libPlatform\windows\os_windows.h" />
+ <ClInclude Include="..\src\lib\util\buffer.h" />
+ <ClInclude Include="..\src\lib\util\misc.h" />
+ <ClInclude Include="..\src\lib\util\StdString.h" />
+ <ClInclude Include="..\src\lib\util\threads.h" />
+ <ClInclude Include="..\src\lib\util\timeutils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\lib\CECDetect.cpp" />
+ <ClCompile Include="..\src\lib\CECDll.cpp" />
+ <ClCompile Include="..\src\lib\CECParser.cpp" />
+ <ClCompile Include="..\src\lib\CECParserC.cpp" />
+ <ClCompile Include="..\src\lib\libPlatform\windows\dlfcn-win32.cpp" />
+ <ClCompile Include="..\src\lib\libPlatform\windows\os_windows.cpp" />
+ <ClCompile Include="..\src\lib\libPlatform\windows\serialport.cpp" />
+ <ClCompile Include="..\src\lib\util\misc.cpp" />
+ <ClCompile Include="..\src\lib\util\threads.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2.lib" />
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2d.lib" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}</ProjectGuid>
+ <RootNamespace>libcec</RootNamespace>
+ <ProjectName>libcec</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(SolutionDir)\..\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>libcec</TargetName>
+ <TargetExt>.dll</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ExtensionsToDeleteOnClean>*.cdf;*.cache;*.obj;*.ilk;*.resources;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.tlog;*.manifest;*.res;*.pch;*.exp;*.idb;*.rep;*.xdc;*.pdb;*_manifest.rc;*.bsc;*.sbr;*.xml;*.dll</ExtensionsToDeleteOnClean>
+ <IncludePath>$(SolutionDir)\..\include;$(IncludePath)</IncludePath>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)..\</OutDir>
+ <TargetName>libcec</TargetName>
+ <TargetExt>.dll</TargetExt>
+ <ExtensionsToDeleteOnClean>*.cdf;*.cache;*.obj;*.ilk;*.resources;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.tlog;*.manifest;*.res;*.pch;*.exp;*.idb;*.rep;*.xdc;*.pdb;*_manifest.rc;*.bsc;*.sbr;*.xml;*.dll</ExtensionsToDeleteOnClean>
+ <IncludePath>$(SolutionDir)\..\include;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;_WINSOCKAPI_;__STDC_CONSTANT_MACROS;__WINDOWS__;DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)\..\src\lib\libPlatform\pthread_win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>$(SolutionDir)\..\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libcmtd</IgnoreSpecificDefaultLibraries>
+ <Version>2</Version>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>$(SolutionDir)\..\src\lib\libPlatform\pthread_win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;_WINSOCKAPI_;__STDC_CONSTANT_MACROS;__WINDOWS__;DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>$(SolutionDir)\..\libcec.dll</OutputFile>
+ <AdditionalDependencies>ws2_32.lib;$(SolutionDir)\..\src\lib\libPlatform\pthread_win32\pthreadVC2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libcmt</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="util">
+ <UniqueIdentifier>{4171e8da-4c9d-40dd-97a3-755ba5535ca6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="platform">
+ <UniqueIdentifier>{cc48ddc0-be11-43ec-a805-3a9434f443ed}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="exports">
+ <UniqueIdentifier>{01b9c84a-dcfe-4bdc-b983-69e3e3929b0f}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\src\lib\util\buffer.h">
+ <Filter>util</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\misc.h">
+ <Filter>util</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\StdString.h">
+ <Filter>util</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\threads.h">
+ <Filter>util</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\os-dependent.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\windows\dlfcn-win32.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\windows\os_windows.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\pthread_win32\pthread.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\pthread_win32\sched.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\pthread_win32\semaphore.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\CECParser.h" />
+ <ClInclude Include="..\include\CECExports.h">
+ <Filter>exports</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\CECExportsCpp.h">
+ <Filter>exports</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\CECTypes.h">
+ <Filter>exports</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\serialport.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\timeutils.h">
+ <Filter>util</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\baudrate.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\CECExportsC.h">
+ <Filter>exports</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\CECDetect.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\lib\util\misc.cpp">
+ <Filter>util</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\util\threads.cpp">
+ <Filter>util</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\libPlatform\windows\dlfcn-win32.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\libPlatform\windows\os_windows.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\CECParser.cpp" />
+ <ClCompile Include="..\src\lib\libPlatform\windows\serialport.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\CECDll.cpp" />
+ <ClCompile Include="..\src\lib\CECParserC.cpp" />
+ <ClCompile Include="..\src\lib\CECDetect.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2.lib">
+ <Filter>platform</Filter>
+ </Library>
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2d.lib">
+ <Filter>platform</Filter>
+ </Library>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F01222BF-6B3D-43BD-B254-434031CB9887}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>testclient</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)\..\</OutDir>
+ <TargetName>cec-client</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)..\</OutDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;_WINSOCKAPI_;__STDC_CONSTANT_MACROS;__WINDOWS__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(SolutionDir)\..\$(TargetName)$(TargetExt)</OutputFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;_WINSOCKAPI_;__STDC_CONSTANT_MACROS;__WINDOWS__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\CECExports.h" />
+ <ClInclude Include="..\include\CECExportsCpp.h" />
+ <ClInclude Include="..\src\lib\libPlatform\os-dependent.h" />
+ <ClInclude Include="..\src\lib\libPlatform\windows\os_windows.h" />
+ <ClInclude Include="..\src\lib\util\misc.h" />
+ <ClInclude Include="..\src\lib\util\StdString.h" />
+ <ClInclude Include="..\src\lib\util\threads.h" />
+ <ClInclude Include="..\src\lib\util\timeutils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\lib\libPlatform\windows\os_windows.cpp" />
+ <ClCompile Include="..\src\lib\util\misc.cpp" />
+ <ClCompile Include="..\src\lib\util\threads.cpp" />
+ <ClCompile Include="..\src\testclient\main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2.lib" />
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2d.lib" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\CECExports.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\CECExportsCpp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\misc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\threads.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\StdString.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\util\timeutils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\os-dependent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\libPlatform\windows\os_windows.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\testclient\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\util\misc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\util\threads.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\lib\libPlatform\windows\os_windows.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2.lib">
+ <Filter>Resource Files</Filter>
+ </Library>
+ <Library Include="..\src\lib\libPlatform\pthread_win32\pthreadVC2d.lib">
+ <Filter>Resource Files</Filter>
+ </Library>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "CECDetect.h"
+#include "libPlatform/os-dependent.h"
+#include "util/StdString.h"
+#if !defined(__WINDOWS__)
+#include <dirent.h>
+#include <libudev.h>
+#include <poll.h>
+#endif
+#include <string.h>
+
+#define CEC_VID 0x2548
+#define CEC_PID 0x1001
+
+using namespace CEC;
+using namespace std;
+
+#if !defined(__WINDOWS__)
+bool TranslateComPort(CStdString &strString)
+{
+ CStdString strTmp(strString);
+ strTmp.MakeReverse();
+ int iSlash = strTmp.Find('/');
+ if (iSlash >= 0)
+ {
+ strTmp = strTmp.Left(iSlash);
+ strTmp.MakeReverse();
+ strString.Format("%s/%s:1.0/tty", strString.c_str(), strTmp.c_str());
+ return true;
+ }
+
+ return false;
+}
+
+bool FindComPort(CStdString &strLocation)
+{
+ CStdString strPort = strLocation;
+ bool bReturn(!strPort.IsEmpty());
+ CStdString strConfigLocation(strLocation);
+ if (TranslateComPort(strConfigLocation))
+ {
+ DIR *dir;
+ struct dirent *dirent;
+ if((dir = opendir(strConfigLocation.c_str())) == NULL)
+ return bReturn;
+
+ while ((dirent = readdir(dir)) != NULL)
+ {
+ if(strcmp((char*)dirent->d_name, "." ) != 0 && strcmp((char*)dirent->d_name, ".." ) != 0)
+ {
+ strPort.Format("/dev/%s", dirent->d_name);
+ if (!strPort.IsEmpty())
+ {
+ strLocation = strPort;
+ bReturn = true;
+ break;
+ }
+ }
+ }
+ closedir(dir);
+ }
+
+ return bReturn;
+}
+#endif
+
+int CCECDetect::FindDevices(vector<cec_device> &deviceList, const char *strDevicePath /* = NULL */)
+{
+ int iFound(0);
+
+#if !defined(__WINDOWS__)
+ struct udev *udev;
+ if (!(udev = udev_new()))
+ return -1;
+
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+ struct udev_device *dev;
+ enumerate = udev_enumerate_new(udev);
+ udev_enumerate_scan_devices(enumerate);
+ devices = udev_enumerate_get_list_entry(enumerate);
+ udev_list_entry_foreach(dev_list_entry, devices)
+ {
+ const char *strPath;
+ strPath = udev_list_entry_get_name(dev_list_entry);
+
+ dev = udev_device_new_from_syspath(udev, strPath);
+ if (!dev)
+ continue;
+
+ dev = udev_device_get_parent(udev_device_get_parent(dev));
+ if (!dev)
+ continue;
+ if (!udev_device_get_sysattr_value(dev,"idVendor") || !udev_device_get_sysattr_value(dev, "idProduct"))
+ {
+ udev_device_unref(dev);
+ continue;
+ }
+
+ int iVendor, iProduct;
+ sscanf(udev_device_get_sysattr_value(dev, "idVendor"), "%x", &iVendor);
+ sscanf(udev_device_get_sysattr_value(dev, "idProduct"), "%x", &iProduct);
+ if (iVendor == CEC_VID && iProduct == CEC_PID)
+ {
+ CStdString strPath(udev_device_get_syspath(dev));
+ if (strDevicePath && strcmp(strPath.c_str(), strDevicePath))
+ continue;
+
+ CStdString strComm(strPath);
+ if (FindComPort(strComm))
+ {
+ cec_device foundDev;
+ foundDev.path = strPath;
+ foundDev.comm = strComm;
+ deviceList.push_back(foundDev);
+ ++iFound;
+ }
+ }
+ udev_device_unref(dev);
+ }
+
+ udev_enumerate_unref(enumerate);
+ udev_unref(udev);
+#endif
+
+ return iFound;
+}
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "../../include/CECExports.h"
+
+namespace CEC
+{
+ class CCECDetect
+ {
+ public:
+ static int FindDevices(std::vector<cec_device> &deviceList, const char *strDevicePath = NULL);
+ };
+};
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "CECExports.h"
+#include "CECParser.h"
+
+using namespace CEC;
+
+int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
+{
+ return 1;
+}
+
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "CECParser.h"
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <sys/stat.h>
+#include "util/StdString.h"
+#include "libPlatform/serialport.h"
+#include "util/threads.h"
+#include "util/timeutils.h"
+#include "CECDetect.h"
+
+using namespace CEC;
+using namespace std;
+
+#define CEC_MAX_RETRY 5
+
+/*!
+ * ICECDevice implementation
+ */
+//@{
+CCECParser::CCECParser(const char *strDeviceName) :
+ m_inbuf(NULL),
+ m_iInbufSize(0),
+ m_iInbufUsed(0),
+ m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
+ m_physicaladdress(CEC_DEFAULT_PHYSICAL_ADDRESS),
+ m_iLogicalAddress(CECDEVICE_PLAYBACKDEVICE1),
+ m_strDeviceName(strDeviceName),
+ m_bRunning(false)
+{
+ m_serialport = new CSerialPort;
+}
+
+CCECParser::~CCECParser(void)
+{
+ m_bRunning = false;
+ pthread_join(m_thread, NULL);
+ m_serialport->Close();
+ delete m_serialport;
+}
+
+bool CCECParser::Open(const char *strPort, int iTimeoutMs /* = 10000 */)
+{
+ bool bReturn(false);
+
+ if (!(bReturn = m_serialport->Open(strPort, 38400)))
+ {
+ CStdString strError;
+ strError.Format("error opening serial port '%s': %s", strPort, m_serialport->GetError().c_str());
+ AddLog(CEC_LOG_ERROR, strError);
+ return bReturn;
+ }
+
+ //clear any input bytes
+ uint8_t buff[1024];
+ m_serialport->Read(buff, sizeof(buff), CEC_SETTLE_DOWN_TIME);
+
+ if (bReturn)
+ bReturn = SetAckMask(m_iLogicalAddress);
+
+ if (!bReturn)
+ {
+ CStdString strError;
+ strError.Format("error opening serial port '%s': %s", strPort, m_serialport->GetError().c_str());
+ AddLog(CEC_LOG_ERROR, strError);
+ return bReturn;
+ }
+
+ if (bReturn)
+ {
+ m_bRunning = true;
+ if (pthread_create(&m_thread, NULL, (void *(*) (void *))&CCECParser::ThreadHandler, (void *)this) == 0)
+ pthread_detach(m_thread);
+ else
+ m_bRunning = false;
+ }
+
+ return bReturn;
+}
+
+void *CCECParser::ThreadHandler(CCECParser *parser)
+{
+ if (parser)
+ parser->Process();
+ return 0;
+}
+
+bool CCECParser::Process(void)
+{
+ int64_t now = GetTimeMs();
+ while (m_bRunning)
+ {
+ {
+ CLockObject lock(&m_mutex, 1000);
+ if (lock.IsLocked())
+ {
+ if (!ReadFromDevice(100))
+ {
+ m_bRunning = false;
+ return false;
+ }
+ }
+ }
+
+ //AddLog(CEC_LOG_DEBUG, "processing messages");
+ ProcessMessages();
+ now = GetTimeMs();
+ CheckKeypressTimeout(now);
+ CCondition::Sleep(50);
+ }
+
+ AddLog(CEC_LOG_DEBUG, "reader thread terminated");
+ m_bRunning = false;
+ return true;
+}
+
+bool CCECParser::Ping(void)
+{
+ AddLog(CEC_LOG_DEBUG, "sending ping");
+ cec_frame output;
+ output.push_back(MSGSTART);
+ PushEscaped(output, MSGCODE_PING);
+ output.push_back(MSGEND);
+
+ if (!TransmitFormatted(output, false, (int64_t) 5000))
+ {
+ AddLog(CEC_LOG_ERROR, "could not send ping command");
+ return false;
+ }
+
+ AddLog(CEC_LOG_DEBUG, "ping tranmitted");
+
+ // TODO check for pong
+ return true;
+}
+
+bool CCECParser::StartBootloader(void)
+{
+ AddLog(CEC_LOG_DEBUG, "starting the bootloader");
+ cec_frame output;
+ output.push_back(MSGSTART);
+ PushEscaped(output, MSGCODE_START_BOOTLOADER);
+ output.push_back(MSGEND);
+
+ if (!TransmitFormatted(output, false, (int64_t) 5000))
+ {
+ AddLog(CEC_LOG_ERROR, "could not start the bootloader");
+ return false;
+ }
+
+ AddLog(CEC_LOG_DEBUG, "bootloader start command transmitted");
+ return true;
+}
+
+uint8_t CCECParser::GetSourceDestination(cec_logical_address destination /* = CECDEVICE_BROADCAST */)
+{
+ return ((uint8_t)m_iLogicalAddress << 4) + (uint8_t)destination;
+}
+
+bool CCECParser::PowerOffDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
+{
+ CStdString strLog;
+ strLog.Format("powering off devices with logical address %d", (int8_t)address);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ cec_frame frame;
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_STANDBY);
+ return Transmit(frame);
+}
+
+bool CCECParser::PowerOnDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
+{
+ CStdString strLog;
+ strLog.Format("powering on devices with logical address %d", (int8_t)address);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ cec_frame frame;
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_TEXT_VIEW_ON);
+ return Transmit(frame);
+}
+
+bool CCECParser::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
+{
+ CStdString strLog;
+ strLog.Format("putting all devices with logical address %d in standby mode", (int8_t)address);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ cec_frame frame;
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_STANDBY);
+ return Transmit(frame);
+}
+
+bool CCECParser::SetActiveView(void)
+{
+ AddLog(CEC_LOG_DEBUG, "setting active view");
+ cec_frame frame;
+ frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
+ frame.push_back(CEC_OPCODE_ACTIVE_SOURCE);
+ frame.push_back((m_physicaladdress >> 8) & 0xFF);
+ frame.push_back(m_physicaladdress & 0xFF);
+ return Transmit(frame);
+}
+
+bool CCECParser::SetInactiveView(void)
+{
+ AddLog(CEC_LOG_DEBUG, "setting inactive view");
+ cec_frame frame;
+ frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
+ frame.push_back(CEC_OPCODE_INACTIVE_SOURCE);
+ frame.push_back((m_physicaladdress >> 8) & 0xFF);
+ frame.push_back(m_physicaladdress & 0xFF);
+ return Transmit(frame);
+}
+
+bool CCECParser::GetNextLogMessage(cec_log_message *message)
+{
+ return m_logBuffer.Pop(*message);
+}
+
+bool CCECParser::GetNextKeypress(cec_keypress *key)
+{
+ return m_keyBuffer.Pop(*key);
+}
+//@}
+
+void CCECParser::TransmitAbort(cec_logical_address address, ECecOpcode opcode, ECecAbortReason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */)
+{
+ AddLog(CEC_LOG_DEBUG, "transmitting abort message");
+ cec_frame frame;
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_FEATURE_ABORT);
+ frame.push_back(opcode);
+ frame.push_back(reason);
+ Transmit(frame);
+}
+
+void CCECParser::ReportCECVersion(cec_logical_address address /* = CECDEVICE_TV */)
+{
+ cec_frame frame;
+ AddLog(CEC_LOG_NOTICE, "reporting CEC version as 1.3a");
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_CEC_VERSION);
+ frame.push_back(CEC_VERSION_1_3A);
+ Transmit(frame);
+}
+
+void CCECParser::ReportPowerState(cec_logical_address address /*= CECDEVICE_TV */, bool bOn /* = true */)
+{
+ cec_frame frame;
+ if (bOn)
+ AddLog(CEC_LOG_NOTICE, "reporting \"On\" power status");
+ else
+ AddLog(CEC_LOG_NOTICE, "reporting \"Off\" power status");
+
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_REPORT_POWER_STATUS);
+ frame.push_back(bOn ? CEC_POWER_STATUS_ON : CEC_POWER_STATUS_STANDBY);
+ Transmit(frame);
+}
+
+void CCECParser::ReportMenuState(cec_logical_address address /* = CECDEVICE_TV */, bool bActive /* = true */)
+{
+ cec_frame frame;
+ if (bActive)
+ AddLog(CEC_LOG_NOTICE, "reporting menu state as active");
+ else
+ AddLog(CEC_LOG_NOTICE, "reporting menu state as inactive");
+
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_MENU_STATUS);
+ frame.push_back(bActive ? CEC_MENU_STATE_ACTIVATED : CEC_MENU_STATE_DEACTIVATED);
+ Transmit(frame);
+}
+
+void CCECParser::ReportVendorID(cec_logical_address address /* = CECDEVICE_TV */)
+{
+ AddLog(CEC_LOG_NOTICE, "vendor ID requested, feature abort");
+ TransmitAbort(address, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+}
+
+void CCECParser::ReportOSDName(cec_logical_address address /* = CECDEVICE_TV */)
+{
+ cec_frame frame;
+ const char *osdname = m_strDeviceName.c_str();
+ CStdString strLog;
+ strLog.Format("reporting OSD name as %s", osdname);
+ AddLog(CEC_LOG_NOTICE, strLog.c_str());
+ frame.push_back(GetSourceDestination(address));
+ frame.push_back(CEC_OPCODE_SET_OSD_NAME);
+
+ for (unsigned int i = 0; i < strlen(osdname); i++)
+ frame.push_back(osdname[i]);
+
+ Transmit(frame);
+}
+
+void CCECParser::ReportPhysicalAddress(void)
+{
+ cec_frame frame;
+ CStdString strLog;
+ strLog.Format("reporting physical address as %04x", m_physicaladdress);
+ AddLog(CEC_LOG_NOTICE, strLog.c_str());
+ frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
+ frame.push_back(CEC_OPCODE_REPORT_PHYSICAL_ADDRESS);
+ frame.push_back((m_physicaladdress >> 8) & 0xFF);
+ frame.push_back(m_physicaladdress & 0xFF);
+ frame.push_back(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ Transmit(frame);
+}
+
+void CCECParser::BroadcastActiveSource(void)
+{
+ cec_frame frame;
+ AddLog(CEC_LOG_NOTICE, "broadcasting active source");
+ frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
+ frame.push_back(CEC_OPCODE_ACTIVE_SOURCE);
+ frame.push_back((m_physicaladdress >> 8) & 0xFF);
+ frame.push_back(m_physicaladdress & 0xFF);
+ Transmit(frame);
+}
+
+bool CCECParser::TransmitFormatted(const cec_frame &data, bool bWaitForAck /* = true */, int64_t iTimeout /* = 2000 */)
+{
+ CLockObject lock(&m_mutex, iTimeout);
+ if (!lock.IsLocked())
+ {
+ AddLog(CEC_LOG_ERROR, "could not get a write lock");
+ return false;
+ }
+
+ if (m_serialport->Write(data) != data.size())
+ {
+ CStdString strError;
+ strError.Format("error writing to serial port: %s", m_serialport->GetError().c_str());
+ AddLog(CEC_LOG_ERROR, strError);
+ return false;
+ }
+ AddLog(CEC_LOG_DEBUG, "command sent");
+
+ CCondition::Sleep((int) data.size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/ + 50 /* to be on the safe side */);
+ if (bWaitForAck && !WaitForAck())
+ {
+ AddLog(CEC_LOG_DEBUG, "did not receive ACK");
+ return false;
+ }
+
+ return true;
+}
+
+bool CCECParser::Transmit(const cec_frame &data, bool bWaitForAck /* = true */, int64_t iTimeout /* = 5000 */)
+{
+ CStdString txStr = "transmit ";
+ for (unsigned int i = 0; i < data.size(); i++)
+ txStr.AppendFormat(" %02x", data[i]);
+ AddLog(CEC_LOG_DEBUG, txStr.c_str());
+
+ if (data.empty())
+ {
+ AddLog(CEC_LOG_WARNING, "transmit buffer is empty");
+ return false;
+ }
+
+ cec_frame output;
+
+ //set ack polarity to high when transmitting to the broadcast address
+ //set ack polarity low when transmitting to any other address
+ output.push_back(MSGSTART);
+ PushEscaped(output, MSGCODE_TRANSMIT_ACK_POLARITY);
+
+ if ((data[0] & 0xF) == 0xF)
+ PushEscaped(output, CEC_TRUE);
+ else
+ PushEscaped(output, CEC_FALSE);
+
+ output.push_back(MSGEND);
+
+ for (unsigned int i = 0; i < data.size(); i++)
+ {
+ output.push_back(MSGSTART);
+
+ if (i == data.size() - 1)
+ PushEscaped(output, MSGCODE_TRANSMIT_EOM);
+ else
+ PushEscaped(output, MSGCODE_TRANSMIT);
+
+ PushEscaped(output, data[i]);
+
+ output.push_back(MSGEND);
+ }
+
+ return TransmitFormatted(output, bWaitForAck, iTimeout);
+}
+
+bool CCECParser::WaitForAck(int64_t iTimeout /* = 1000 */)
+{
+ bool bGotAck(false);
+ bool bError(false);
+
+ int64_t iNow = GetTimeMs();
+ int64_t iTargetTime = iNow + iTimeout;
+
+ while (!bGotAck && !bError && (iTimeout <= 0 || iNow < iTargetTime))
+ {
+ if (!ReadFromDevice((int) iTimeout))
+ {
+ AddLog(CEC_LOG_ERROR, "failed to read from device");
+ return false;
+ }
+
+ cec_frame msg;
+ while (!bGotAck && !bError && GetMessage(msg, false))
+ {
+ uint8_t iCode = msg[0] & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK);
+
+ switch (iCode)
+ {
+ case MSGCODE_COMMAND_ACCEPTED:
+ AddLog(CEC_LOG_DEBUG, "MSGCODE_COMMAND_ACCEPTED");
+ break;
+ case MSGCODE_TRANSMIT_SUCCEEDED:
+ AddLog(CEC_LOG_DEBUG, "MSGCODE_TRANSMIT_SUCCEEDED");
+ // TODO
+ bGotAck = true;
+ break;
+ case MSGCODE_RECEIVE_FAILED:
+ AddLog(CEC_LOG_WARNING, "MSGCODE_RECEIVE_FAILED");
+ bError = true;
+ break;
+ case MSGCODE_COMMAND_REJECTED:
+ AddLog(CEC_LOG_WARNING, "MSGCODE_COMMAND_REJECTED");
+ bError = true;
+ break;
+ case MSGCODE_TRANSMIT_FAILED_LINE:
+ AddLog(CEC_LOG_WARNING, "MSGCODE_TRANSMIT_FAILED_LINE");
+ bError = true;
+ break;
+ case MSGCODE_TRANSMIT_FAILED_ACK:
+ AddLog(CEC_LOG_WARNING, "MSGCODE_TRANSMIT_FAILED_ACK");
+ bError = true;
+ break;
+ case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
+ AddLog(CEC_LOG_WARNING, "MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA");
+ bError = true;
+ break;
+ case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+ AddLog(CEC_LOG_WARNING, "MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE");
+ bError = true;
+ break;
+ default:
+ m_frameBuffer.Push(msg);
+ bGotAck = (msg[0] & MSGCODE_FRAME_ACK) != 0;
+ break;
+ }
+ iNow = GetTimeMs();
+ }
+ }
+
+ return bGotAck && !bError;
+}
+
+bool CCECParser::ReadFromDevice(int iTimeout)
+{
+ uint8_t buff[1024];
+ int iBytesRead = m_serialport->Read(buff, sizeof(buff), iTimeout);
+ if (iBytesRead < 0)
+ {
+ CStdString strError;
+ strError.Format("error reading from serial port: %s", m_serialport->GetError().c_str());
+ AddLog(CEC_LOG_ERROR, strError);
+ return false;
+ }
+ else if (iBytesRead > 0)
+ AddData(buff, iBytesRead);
+
+ return true;
+}
+
+void CCECParser::ProcessMessages(void)
+{
+ cec_frame msg;
+ while (GetMessage(msg))
+ ParseMessage(msg);
+}
+
+bool CCECParser::GetMessage(cec_frame &msg, bool bFromBuffer /* = true */)
+{
+ if (bFromBuffer && m_frameBuffer.Pop(msg))
+ return true;
+
+ if (m_iInbufUsed < 1)
+ return false;
+
+ //search for first start of message
+ int startpos = -1;
+ for (int i = 0; i < m_iInbufUsed; i++)
+ {
+ if (m_inbuf[i] == MSGSTART)
+ {
+ startpos = i;
+ break;
+ }
+ }
+
+ if (startpos == -1)
+ return false;
+
+ //move anything from the first start of message to the beginning of the buffer
+ if (startpos > 0)
+ {
+ memmove(m_inbuf, m_inbuf + startpos, m_iInbufUsed - startpos);
+ m_iInbufUsed -= startpos;
+ }
+
+ if (m_iInbufUsed < 2)
+ return false;
+
+ //look for end of message
+ startpos = -1;
+ int endpos = -1;
+ for (int i = 1; i < m_iInbufUsed; i++)
+ {
+ if (m_inbuf[i] == MSGEND)
+ {
+ endpos = i;
+ break;
+ }
+ else if (m_inbuf[i] == MSGSTART)
+ {
+ startpos = i;
+ break;
+ }
+ }
+
+ if (startpos > 0) //we found a msgstart before msgend, this is not right, remove
+ {
+ AddLog(CEC_LOG_ERROR, "received MSGSTART before MSGEND");
+ memmove(m_inbuf, m_inbuf + startpos, m_iInbufUsed - startpos);
+ m_iInbufUsed -= startpos;
+ return false;
+ }
+
+ if (endpos > 0) //found a MSGEND
+ {
+ msg.clear();
+ bool isesc = false;
+ for (int i = 1; i < endpos; i++)
+ {
+ if (isesc)
+ {
+ msg.push_back(m_inbuf[i] + (uint8_t)ESCOFFSET);
+ isesc = false;
+ }
+ else if (m_inbuf[i] == MSGESC)
+ {
+ isesc = true;
+ }
+ else
+ {
+ msg.push_back(m_inbuf[i]);
+ }
+ }
+
+ if (endpos + 1 < m_iInbufUsed)
+ memmove(m_inbuf, m_inbuf + endpos + 1, m_iInbufUsed - endpos - 1);
+
+ m_iInbufUsed -= endpos + 1;
+
+ return true;
+ }
+
+ return false;
+}
+
+void CCECParser::ParseMessage(cec_frame &msg)
+{
+ if (msg.empty())
+ return;
+
+ CStdString logStr;
+ uint8_t iCode = msg[0] & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK);
+ bool bEom = (msg[0] & MSGCODE_FRAME_EOM) != 0;
+ bool bAck = (msg[0] & MSGCODE_FRAME_ACK) != 0;
+
+ switch(iCode)
+ {
+ case MSGCODE_NOTHING:
+ AddLog(CEC_LOG_DEBUG, "MSGCODE_NOTHING");
+ break;
+ case MSGCODE_TIMEOUT_ERROR:
+ case MSGCODE_HIGH_ERROR:
+ case MSGCODE_LOW_ERROR:
+ {
+ if (iCode == MSGCODE_TIMEOUT_ERROR)
+ logStr = "MSGCODE_TIMEOUT";
+ else if (iCode == MSGCODE_HIGH_ERROR)
+ logStr = "MSGCODE_HIGH_ERROR";
+ else
+ logStr = "MSGCODE_LOW_ERROR";
+
+ int iLine = (msg.size() >= 3) ? (msg[1] << 8) | (msg[2]) : 0;
+ uint32_t iTime = (msg.size() >= 7) ? (msg[3] << 24) | (msg[4] << 16) | (msg[5] << 8) | (msg[6]) : 0;
+ logStr.AppendFormat(" line:%i", iLine);
+ logStr.AppendFormat(" time:%u", iTime);
+ AddLog(CEC_LOG_WARNING, logStr.c_str());
+ }
+ break;
+ case MSGCODE_FRAME_START:
+ {
+ logStr = "MSGCODE_FRAME_START";
+ m_currentframe.clear();
+ if (msg.size() >= 2)
+ {
+ int iInitiator = msg[1] >> 4;
+ int iDestination = msg[1] & 0xF;
+ logStr.AppendFormat(" initiator:%u destination:%u ack:%s %s", iInitiator, iDestination, bAck ? "high" : "low", bEom ? "eom" : "");
+
+ m_currentframe.push_back(msg[1]);
+ }
+ AddLog(CEC_LOG_DEBUG, logStr.c_str());
+ }
+ break;
+ case MSGCODE_FRAME_DATA:
+ {
+ logStr = "MSGCODE_FRAME_DATA";
+ if (msg.size() >= 2)
+ {
+ uint8_t iData = msg[1];
+ logStr.AppendFormat(" %02x", iData);
+ m_currentframe.push_back(iData);
+ }
+ AddLog(CEC_LOG_DEBUG, logStr.c_str());
+ }
+ if (bEom)
+ ParseCurrentFrame();
+ break;
+ default:
+ break;
+ }
+}
+
+void CCECParser::ParseCurrentFrame(void)
+{
+ uint8_t initiator = m_currentframe[0] >> 4;
+ uint8_t destination = m_currentframe[0] & 0xF;
+
+ CStdString dataStr;
+ dataStr.Format("received frame: initiator: %u destination: %u", initiator, destination);
+
+ if (m_currentframe.size() > 1)
+ {
+ dataStr += " data:";
+ for (unsigned int i = 1; i < m_currentframe.size(); i++)
+ dataStr.AppendFormat(" %02x", m_currentframe[i]);
+ }
+ AddLog(CEC_LOG_DEBUG, dataStr.c_str());
+
+ if (m_currentframe.size() <= 1)
+ return;
+
+ vector<uint8_t> tx;
+ ECecOpcode opCode = (ECecOpcode) m_currentframe[1];
+ if (destination == (uint16_t) m_iLogicalAddress)
+ {
+ switch(opCode)
+ {
+ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+ ReportPhysicalAddress();
+ SetActiveView();
+ break;
+ case CEC_OPCODE_GIVE_OSD_NAME:
+ ReportOSDName((cec_logical_address)initiator);
+ break;
+ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
+ ReportVendorID((cec_logical_address)initiator);
+ break;
+ case CEC_OPCODE_MENU_REQUEST:
+ ReportMenuState((cec_logical_address)initiator);
+ break;
+ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
+ ReportPowerState((cec_logical_address)initiator);
+ break;
+ case CEC_OPCODE_GET_CEC_VERSION:
+ ReportCECVersion((cec_logical_address)initiator);
+ break;
+ case CEC_OPCODE_USER_CONTROL_PRESSED:
+ if (m_currentframe.size() > 2)
+ {
+ AddKey();
+
+ if (m_currentframe[2] <= CEC_USER_CONTROL_CODE_MAX)
+ {
+ m_iCurrentButton = (cec_user_control_code) m_currentframe[2];
+ m_buttontime = GetTimeMs();
+ }
+ }
+ break;
+ case CEC_OPCODE_USER_CONTROL_RELEASE:
+ AddKey();
+ break;
+ default:
+ break;
+ }
+ }
+ else if (destination == (uint8_t) CECDEVICE_BROADCAST)
+ {
+ if (opCode == CEC_OPCODE_REQUEST_ACTIVE_SOURCE)
+ {
+ BroadcastActiveSource();
+ }
+ else if (opCode == CEC_OPCODE_SET_STREAM_PATH)
+ {
+ if (m_currentframe.size() >= 4)
+ {
+ int streamaddr = ((int)m_currentframe[2] << 8) | ((int)m_currentframe[3]);
+ CStdString strLog;
+ strLog.Format("%i requests stream path from physical address %04x", initiator, streamaddr);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ if (streamaddr == m_physicaladdress)
+ BroadcastActiveSource();
+ }
+ }
+ }
+ else
+ {
+ CStdString strLog;
+ strLog.Format("ignoring frame: destination: %u != %u", destination, (uint16_t)m_iLogicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ }
+}
+
+void CCECParser::AddData(uint8_t *data, int iLen)
+{
+ if (iLen + m_iInbufUsed > m_iInbufSize)
+ {
+ m_iInbufSize = iLen + m_iInbufUsed;
+ m_inbuf = (uint8_t*)realloc(m_inbuf, m_iInbufSize);
+ }
+
+ memcpy(m_inbuf + m_iInbufUsed, data, iLen);
+ m_iInbufUsed += iLen;
+}
+
+void CCECParser::PushEscaped(cec_frame &vec, uint8_t byte)
+{
+ if (byte >= MSGESC && byte != MSGSTART)
+ {
+ vec.push_back(MSGESC);
+ vec.push_back(byte - ESCOFFSET);
+ }
+ else
+ {
+ vec.push_back(byte);
+ }
+}
+
+void CCECParser::CheckKeypressTimeout(int64_t now)
+{
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && now - m_buttontime > 500)
+ {
+ AddKey();
+ m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
+ }
+}
+
+bool CCECParser::SetAckMask(cec_logical_address ackmask)
+{
+ CStdString strLog;
+ strLog.Format("setting ackmask to %d", (uint16_t) ackmask);
+ AddLog(CEC_LOG_NOTICE, strLog.c_str());
+
+ //TODO!!
+ uint16_t tackmask = 0x10;
+ AddLog(CEC_LOG_WARNING, "TODO: forcing ackmask to 0x10");
+
+ cec_frame output;
+ m_iLogicalAddress = ackmask;
+ output.push_back(MSGSTART);
+
+ PushEscaped(output, MSGCODE_SET_ACK_MASK);
+ PushEscaped(output, tackmask >> 8);
+ PushEscaped(output, (uint8_t) tackmask);
+
+ output.push_back(MSGEND);
+
+ if (m_serialport->Write(output) == -1)
+ {
+ CStdString strError;
+ strError.Format("error writing to serial port: %s", m_serialport->GetError().c_str());
+ AddLog(CEC_LOG_ERROR, strError);
+ return false;
+ }
+
+ return true;
+}
+
+void CCECParser::AddLog(cec_log_level level, const string &strMessage)
+{
+ cec_log_message message;
+ message.level = level;
+ message.message.assign(strMessage.c_str());
+ m_logBuffer.Push(message);
+}
+
+void CCECParser::AddKey(void)
+{
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
+ {
+ cec_keypress key;
+ key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
+ key.keycode = m_iCurrentButton;
+ m_keyBuffer.Push(key);
+ m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
+ m_buttontime = 0;
+ }
+}
+
+int CCECParser::GetMinVersion(void)
+{
+ return CEC_MIN_VERSION;
+}
+
+int CCECParser::GetLibVersion(void)
+{
+ return CEC_LIB_VERSION;
+}
+
+int CCECParser::FindDevices(std::vector<cec_device> &deviceList, const char *strDevicePath /* = NULL */)
+{
+ CStdString strDebug;
+ if (strDevicePath)
+ strDebug.Format("trying to autodetect the com port for device path '%s'", strDevicePath);
+ else
+ strDebug.Format("trying to autodetect all CEC adapters");
+ AddLog(CEC_LOG_DEBUG, strDebug);
+
+ return CCECDetect::FindDevices(deviceList, strDevicePath);
+}
+
+DECLSPEC void * CECCreate(const char *strDeviceName)
+{
+ return static_cast< void* > (new CCECParser(strDeviceName));
+}
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include <queue>
+#include <stdio.h>
+#include "../../include/CECExports.h"
+#include "../../include/CECTypes.h"
+#include "util/buffer.h"
+
+class CSerialPort;
+
+namespace CEC
+{
+ class CCECParser : public ICECDevice
+ {
+ public:
+ /*!
+ * ICECDevice implementation
+ */
+ //@{
+ CCECParser(const char *strDeviceName);
+ virtual ~CCECParser(void);
+
+ virtual bool Open(const char *strPort, int iTimeout = 10000);
+ virtual int FindDevices(std::vector<cec_device> &deviceList, const char *strDevicePath = NULL);
+ virtual bool Ping(void);
+ virtual bool StartBootloader(void);
+ virtual bool PowerOffDevices(cec_logical_address address = CECDEVICE_BROADCAST);
+ virtual bool PowerOnDevices(cec_logical_address address = CECDEVICE_BROADCAST);
+ virtual bool StandbyDevices(cec_logical_address address = CECDEVICE_BROADCAST);
+ virtual bool SetActiveView(void);
+ virtual bool SetInactiveView(void);
+ virtual bool GetNextLogMessage(cec_log_message *message);
+ virtual bool GetNextKeypress(cec_keypress *key);
+ virtual bool Transmit(const cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 5000);
+ virtual bool SetAckMask(cec_logical_address ackmask);
+ virtual int GetMinVersion(void);
+ virtual int GetLibVersion(void);
+ //@}
+
+ static void *ThreadHandler(CCECParser *parser);
+ bool Process(void);
+ protected:
+ virtual bool TransmitFormatted(const cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 2000);
+ virtual void TransmitAbort(cec_logical_address address, ECecOpcode opcode, ECecAbortReason reason = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE);
+ virtual void ReportCECVersion(cec_logical_address address = CECDEVICE_TV);
+ virtual void ReportPowerState(cec_logical_address address = CECDEVICE_TV, bool bOn = true);
+ virtual void ReportMenuState(cec_logical_address address = CECDEVICE_TV, bool bActive = true);
+ virtual void ReportVendorID(cec_logical_address address = CECDEVICE_TV);
+ virtual void ReportOSDName(cec_logical_address address = CECDEVICE_TV);
+ virtual void ReportPhysicalAddress(void);
+ virtual void BroadcastActiveSource(void);
+ virtual uint8_t GetSourceDestination(cec_logical_address destination = CECDEVICE_BROADCAST);
+
+ private:
+ void AddKey(void);
+ void AddLog(cec_log_level level, const std::string &strMessage);
+ bool WaitForAck(int64_t iTimeout = (int64_t) 1000);
+ bool ReadFromDevice(int iTimeout);
+ void ProcessMessages(void);
+ bool GetMessage(cec_frame &msg, bool bFromBuffer = true);
+ void ParseMessage(cec_frame &msg);
+ void ParseCurrentFrame(void);
+
+ void AddData(uint8_t* data, int len);
+ void PushEscaped(cec_frame &vec, uint8_t iByte);
+
+ void CheckKeypressTimeout(int64_t now);
+
+ uint8_t* m_inbuf;
+ int m_iInbufSize;
+ int m_iInbufUsed;
+ CSerialPort * m_serialport;
+ cec_frame m_currentframe;
+ cec_user_control_code m_iCurrentButton;
+ int64_t m_buttontime;
+ int m_physicaladdress;
+ cec_logical_address m_iLogicalAddress;
+ CecBuffer<cec_frame> m_frameBuffer;
+ CecBuffer<cec_log_message> m_logBuffer;
+ CecBuffer<cec_keypress> m_keyBuffer;
+ std::string m_strDeviceName;
+ pthread_t m_thread;
+ CMutex m_mutex;
+ bool m_bRunning;
+ };
+};
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "CECParser.h"
+
+using namespace CEC;
+using namespace std;
+
+/*!
+ * C interface implementation
+ */
+//@{
+ICECDevice *cec_parser;
+
+bool cec_init(const char *strDeviceName)
+{
+ cec_parser = (ICECDevice *) CECCreate(strDeviceName);
+ return (cec_parser != NULL);
+}
+
+bool cec_close(void)
+{
+ delete cec_parser;
+ cec_parser = NULL;
+ return true;
+}
+
+bool cec_open(const char *strPort, int iTimeout)
+{
+ if (cec_parser)
+ return cec_parser->Open(strPort, iTimeout);
+ return false;
+}
+
+bool cec_ping(void)
+{
+ if (cec_parser)
+ return cec_parser->Ping();
+ return false;
+}
+
+bool cec_start_bootloader(void)
+{
+ if (cec_parser)
+ return cec_parser->StartBootloader();
+ return false;
+}
+
+bool cec_power_off_devices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
+{
+ if (cec_parser)
+ return cec_parser->PowerOffDevices(address);
+ return false;
+}
+
+bool cec_power_on_devices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
+{
+ if (cec_parser)
+ return cec_parser->PowerOnDevices(address);
+ return false;
+}
+
+bool cec_standby_devices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
+{
+ if (cec_parser)
+ return cec_parser->StandbyDevices(address);
+ return false;
+}
+
+bool cec_set_active_view(void)
+{
+ if (cec_parser)
+ return cec_parser->SetActiveView();
+ return false;
+}
+
+bool cec_set_inactive_view(void)
+{
+ if (cec_parser)
+ return cec_parser->SetInactiveView();
+ return false;
+}
+
+bool cec_get_next_log_message(cec_log_message *message)
+{
+ if (cec_parser)
+ return cec_parser->GetNextLogMessage(message);
+ return false;
+}
+
+bool cec_get_next_keypress(cec_keypress *key)
+{
+ if (cec_parser)
+ return cec_parser->GetNextKeypress(key);
+ return false;
+}
+
+bool cec_transmit(const CEC::cec_frame &data, bool bWaitForAck /* = true */, int64_t iTimeout /* = 2000 */)
+{
+ if (cec_parser)
+ return cec_parser->Transmit(data, bWaitForAck, iTimeout);
+ return false;
+}
+
+bool cec_set_ack_mask(uint16_t ackmask)
+{
+ if (cec_parser)
+ return cec_parser->SetAckMask((cec_logical_address) ackmask);
+ return false;
+}
+
+int cec_get_min_version(void)
+{
+ if (cec_parser)
+ return cec_parser->GetMinVersion();
+ return -1;
+}
+
+int cec_get_lib_version(void)
+{
+ if (cec_parser)
+ return cec_parser->GetLibVersion();
+ return -1;
+}
+
+int cec_find_devices(vector<cec_device> &deviceList, const char *strDevicePath /* = NULL */)
+{
+ if (cec_parser)
+ return cec_parser->FindDevices(deviceList, strDevicePath);
+ return -1;
+}
+
+//@}
--- /dev/null
+lib_LTLIBRARIES = libcec.la
+library_includedir=$(includedir)/libcec
+library_include_HEADERS = ../../include/CECExports.h \
+ ../../include/CECExportsCpp.h \
+ ../../include/CECExportsC.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libcec.pc
+
+
+libcec_la_SOURCES = CECParser.cpp \
+ CECParser.h \
+ CECParserC.cpp \
+ CECDetect.cpp \
+ CECDetect.h \
+ ../../include/CECExports.h \
+ ../../include/CECExportsCpp.h \
+ ../../include/CECExportsC.h \
+ util/misc.h \
+ util/misc.cpp \
+ util/StdString.h \
+ util/threads.cpp \
+ util/threads.h \
+ util/timeutils.h \
+ libPlatform/baudrate.h \
+ libPlatform/os-dependent.h \
+ libPlatform/linux/os_posix.h \
+ libPlatform/linux/serialport.cpp \
+ libPlatform/serialport.h
+
+libcec_la_LDFLAGS = -lrt -lpthread -ludev -version-info @VERSION@
--- /dev/null
+#pragma once
+
+/*
+ * boblight
+ * Copyright (C) Bob 2009
+ *
+ * boblight is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * boblight is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+
+//every baudrate I could find is in here in an #ifdef block
+//so it should compile on everything
+
+static struct sbaudrate
+{
+ int rate;
+ int symbol;
+}
+baudrates[] =
+{
+#ifdef B50
+ { 50, B50 },
+#endif
+#ifdef B75
+ { 75, B75 },
+#endif
+#ifdef B110
+ { 110, B110 },
+#endif
+#ifdef B134
+ { 134, B134 },
+#endif
+#ifdef B150
+ { 150, B150 },
+#endif
+#ifdef B200
+ { 200, B200 },
+#endif
+#ifdef B300
+ { 300, B300 },
+#endif
+#ifdef B600
+ { 600, B600 },
+#endif
+#ifdef B1200
+ { 1200, B1200 },
+#endif
+#ifdef B1800
+ { 1800, B1800 },
+#endif
+#ifdef B2400
+ { 2400, B2400 },
+#endif
+#ifdef B4800
+ { 4800, B4800 },
+#endif
+#ifdef B9600
+ { 9600, B9600 },
+#endif
+#ifdef B14400
+ { 14400, B14400 },
+#endif
+#ifdef B19200
+ { 19200, B19200 },
+#endif
+#ifdef B28800
+ { 28800, B28800 },
+#endif
+#ifdef B38400
+ { 38400, B38400 },
+#endif
+#ifdef B57600
+ { 57600, B57600 },
+#endif
+#ifdef B76800
+ { 76800, B76800 },
+#endif
+#ifdef B115200
+ { 115200, B115200 },
+#endif
+#ifdef B230400
+ { 230400, B230400 },
+#endif
+#ifdef B250000
+ { 250000, B250000 },
+#endif
+#ifdef B460800
+ { 460800, B460800 },
+#endif
+#ifdef B500000
+ { 500000, B500000 },
+#endif
+#ifdef B576000
+ { 576000, B576000 },
+#endif
+#ifdef B921600
+ { 921600, B921600 },
+#endif
+#ifdef B1000000
+ { 1000000, B1000000 },
+#endif
+#ifdef B1152000
+ { 1152000, B1152000 },
+#endif
+#ifdef B1500000
+ { 1500000, B1500000 },
+#endif
+#ifdef B2000000
+ { 2000000, B2000000 },
+#endif
+#ifdef B2500000
+ { 2500000, B2500000 },
+#endif
+#ifdef B3000000
+ { 3000000, B3000000 },
+#endif
+#ifdef B3500000
+ { 3500000, B3500000 },
+#endif
+#ifdef B4000000
+ { 4000000, B4000000 },
+#endif
+#ifdef CBR_110
+ { 110, CBR_110 },
+#endif
+#ifdef CBR_300
+ { 300, CBR_300 },
+#endif
+#ifdef CBR_600
+ { 600, CBR_600 },
+#endif
+#ifdef CBR_1200
+ { 1200, CBR_1200 },
+#endif
+#ifdef CBR_2400
+ { 2400, CBR_2400 },
+#endif
+#ifdef CBR_4800
+ { 4800, CBR_4800 },
+#endif
+#ifdef CBR_9600
+ { 9600, CBR_9600 },
+#endif
+#ifdef CBR_11400
+ { 11400, CBR_14400 },
+#endif
+#ifdef CBR_19200
+ { 19200, CBR_19200 },
+#endif
+#ifdef CBR_38400
+ { 38400, CBR_38400 },
+#endif
+#ifdef CBR_56000
+ { 56000, CBR_56000 },
+#endif
+#ifdef CBR_57600
+ { 57600, CBR_57600 },
+#endif
+#ifdef CBR_115200
+ { 115200, CBR_115200 },
+#endif
+#ifdef CBR_128000
+ { 128000, CBR_128000 },
+#endif
+#ifdef CBR_256000
+ { 256000, CBR_256000 },
+#endif
+ { -1, -1}
+};
--- /dev/null
+#pragma once
+/*
+ * Copyright (C) 2005-2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define _FILE_OFFSET_BITS 64
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#ifndef __APPLE__
+#include <sys/prctl.h>
+#endif
+#include <pthread.h>
+#include <poll.h>
+#include <semaphore.h>
+
+#define LIBTYPE
+#define DECLSPEC
+
+#ifndef _STL_ALGOBASE_H
+template<class T> inline T min(T a, T b) { return a <= b ? a : b; }
+template<class T> inline T max(T a, T b) { return a >= b ? a : b; }
+template<class T> inline int sgn(T a) { return a < 0 ? -1 : a > 0 ? 1 : 0; }
+template<class T> inline void swap(T &a, T &b) { T t = a; a = b; b = t; }
+#endif
+
+/*!
+ * @return the current time in seconds since unix epoch.
+ */
+static inline uint64_t getcurrenttime(void)
+{
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000);
+}
--- /dev/null
+/*
+ * boblight
+ * Copyright (C) Bob 2009
+ *
+ * boblight is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * boblight is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>//debug
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "../serialport.h"
+#include "../baudrate.h"
+#include "../../util/misc.h"
+#include "../../util/timeutils.h"
+
+using namespace std;
+
+CSerialPort::CSerialPort()
+{
+ m_fd = -1;
+}
+
+CSerialPort::~CSerialPort()
+{
+ Close();
+}
+
+int CSerialPort::Write(uint8_t* data, int len)
+{
+ fd_set port;
+
+ if (m_fd == -1)
+ {
+ m_error = "port closed";
+ return -1;
+ }
+
+ int byteswritten = 0;
+
+ while (byteswritten < len)
+ {
+ FD_ZERO(&port);
+ FD_SET(m_fd, &port);
+ int returnv = select(m_fd + 1, NULL, &port, NULL, NULL);
+ if (returnv == -1)
+ {
+ m_error = GetErrno();
+ return -1;
+ }
+
+ returnv = write(m_fd, data + byteswritten, len - byteswritten);
+ if (returnv == -1)
+ {
+ m_error = GetErrno();
+ return -1;
+ }
+ byteswritten += returnv;
+ }
+
+ //print what's written to stdout for debugging
+// if (m_tostdout)
+// {
+// printf("%s write:", m_name.c_str());
+// for (int i = 0; i < byteswritten; i++)
+// printf(" %02x", (unsigned int)data[i]);
+
+// printf("\n");
+// }
+
+ return byteswritten;
+}
+
+int CSerialPort::Read(uint8_t* data, int len, int iTimeoutMs /*= -1*/)
+{
+ fd_set port;
+ struct timeval timeout, *tv;
+ int64_t now, target;
+ int bytesread = 0;
+
+ if (m_fd == -1)
+ {
+ m_error = "port closed";
+ return -1;
+ }
+
+ if (iTimeoutMs >= 0)
+ {
+ now = GetTimeMs();
+ target = now + (int64_t) iTimeoutMs;
+ }
+
+ while (bytesread < len && (iTimeoutMs < 0 || target > now))
+ {
+ if (iTimeoutMs < 0)
+ {
+ tv = NULL;
+ }
+ else
+ {
+ timeout.tv_sec = ((long int)target - (long int)now) / (long int)1000.;
+ timeout.tv_usec = ((long int)target - (long int)now) % (long int)1000.;
+ tv = &timeout;
+ }
+
+ FD_ZERO(&port);
+ FD_SET(m_fd, &port);
+ int returnv = select(m_fd + 1, &port, NULL, NULL, tv);
+
+ if (returnv == -1)
+ {
+ m_error = GetErrno();
+ return -1;
+ }
+ else if (returnv == 0)
+ {
+ break; //nothing to read
+ }
+
+ returnv = read(m_fd, data + bytesread, len - bytesread);
+ if (returnv == -1)
+ {
+ m_error = GetErrno();
+ return -1;
+ }
+
+ bytesread += returnv;
+
+ if (iTimeoutMs > 0)
+ now = GetTimeMs();
+ }
+
+ //print what's read to stdout for debugging
+// if (m_tostdout && bytesread > 0)
+// {
+// printf("%s read:", m_name.c_str());
+// for (int i = 0; i < bytesread; i++)
+// printf(" %02x", (unsigned int)data[i]);
+//
+// printf("\n");
+// }
+
+ return bytesread;
+}
+
+//setting all this stuff up is a pain in the ass
+bool CSerialPort::Open(string name, int baudrate, int databits/* = 8*/, int stopbits/* = 1*/, int parity/* = PAR_NONE*/)
+{
+ m_name = name;
+ m_error = GetErrno();
+
+ if (databits < 5 || databits > 8)
+ {
+ m_error = "Databits has to be between 5 and 8";
+ return false;
+ }
+
+ if (stopbits != 1 && stopbits != 2)
+ {
+ m_error = "Stopbits has to be 1 or 2";
+ return false;
+ }
+
+ if (parity != PAR_NONE && parity != PAR_EVEN && parity != PAR_ODD)
+ {
+ m_error = "Parity has to be none, even or odd";
+ return false;
+ }
+
+ m_fd = open(name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+
+ if (m_fd == -1)
+ {
+ m_error = GetErrno();
+ return false;
+ }
+
+ fcntl(m_fd, F_SETFL, 0);
+
+ if (!SetBaudRate(baudrate))
+ {
+ return false;
+ }
+
+ m_options.c_cflag |= (CLOCAL | CREAD);
+ m_options.c_cflag &= ~HUPCL;
+
+ m_options.c_cflag &= ~CSIZE;
+ if (databits == 5) m_options.c_cflag |= CS5;
+ if (databits == 6) m_options.c_cflag |= CS6;
+ if (databits == 7) m_options.c_cflag |= CS7;
+ if (databits == 8) m_options.c_cflag |= CS8;
+
+ m_options.c_cflag &= ~PARENB;
+ if (parity == PAR_EVEN || parity == PAR_ODD)
+ m_options.c_cflag |= PARENB;
+ if (parity == PAR_ODD)
+ m_options.c_cflag |= PARODD;
+
+#ifdef CRTSCTS
+ m_options.c_cflag &= ~CRTSCTS;
+#elif defined(CNEW_RTSCTS)
+ m_options.c_cflag &= ~CNEW_RTSCTS;
+#endif
+
+ if (stopbits == 1) m_options.c_cflag &= ~CSTOPB;
+ else m_options.c_cflag |= CSTOPB;
+
+ //I guessed a little here
+ m_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | XCASE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | TOSTOP);
+
+ if (parity == PAR_NONE)
+ {
+ m_options.c_iflag &= ~INPCK;
+ }
+ else
+ {
+ m_options.c_iflag |= INPCK | ISTRIP;
+ }
+
+ m_options.c_iflag &= ~(IXON | IXOFF | IXANY | BRKINT | INLCR | IGNCR | ICRNL | IUCLC | IMAXBEL);
+ m_options.c_oflag &= ~(OPOST | ONLCR | OCRNL);
+
+ if (tcsetattr(m_fd, TCSANOW, &m_options) != 0)
+ {
+ m_error = GetErrno();
+ return false;
+ }
+
+ //non-blocking port
+ fcntl(m_fd, F_SETFL, FNDELAY);
+
+ return true;
+}
+
+void CSerialPort::Close()
+{
+ if (m_fd != -1)
+ {
+ close(m_fd);
+ m_fd = -1;
+ m_name = "";
+ m_error = "";
+ }
+}
+
+bool CSerialPort::SetBaudRate(int baudrate)
+{
+ int rate = IntToRate(baudrate);
+ if (rate == -1)
+ {
+ char buff[255];
+ sprintf(buff, "%i is not a valid baudrate", baudrate);
+ m_error = buff;
+ return false;
+ }
+
+ //get the current port attributes
+ if (tcgetattr(m_fd, &m_options) != 0)
+ {
+ m_error = GetErrno();
+ return false;
+ }
+
+ if (cfsetispeed(&m_options, rate) != 0)
+ {
+ m_error = GetErrno();
+ return false;
+ }
+
+ if (cfsetospeed(&m_options, rate) != 0)
+ {
+ m_error = GetErrno();
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+#pragma once
+/*
+ * Copyright (C) 2005-2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if defined(_WIN32) || defined(_WIN64)
+#ifndef __WINDOWS__
+#define __WINDOWS__
+#endif
+#endif
+
+#if defined(__WINDOWS__)
+#include "windows/os_windows.h"
+#else
+#include "linux/os_posix.h"
+#endif
+
+#if !defined(TRUE)
+#define TRUE 1
+#endif
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
--- /dev/null
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+/*
+ * See the README file for an explanation of the pthreads-win32 version
+ * numbering scheme and how the DLL is named etc.
+ */
+#define PTW32_VERSION 2,8,0,0
+#define PTW32_VERSION_STRING "2, 8, 0, 0\0"
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ * WIN32 SEH
+ * C
+ * C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard C style cleanup. This style uses setjmp/longjmp
+ * in the cancelation and thread exit implementations and therefore won't
+ * do stack unwinding if linked to applications that have it (e.g.
+ * C++ apps). This is currently consistent with most/all commercial Unix
+ * POSIX threads implementations.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
+#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
+#endif
+
+/*
+ * Stop here if we are being included by the resource compiler.
+ */
+#ifndef RC_INVOKED
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#ifdef _UWIN
+# define HAVE_STRUCT_TIMESPEC 1
+# define HAVE_SIGNAL_H 1
+# undef HAVE_CONFIG_H
+# pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ * Provides an implementation of PThreads based upon the
+ * standard:
+ *
+ * POSIX 1003.1-2001
+ * and
+ * The Single Unix Specification version 3
+ *
+ * (these two are equivalent)
+ *
+ * in order to enhance code portability between Windows,
+ * various commercial Unix implementations, and Linux.
+ *
+ * See the ANNOUNCE file for a full list of conforming
+ * routines and defined constants, and a list of missing
+ * routines and constants not defined in this implementation.
+ *
+ * Authors:
+ * There have been many contributors to this library.
+ * The initial implementation was contributed by
+ * John Bossom, and several others have provided major
+ * sections or revisions of parts of the implementation.
+ * Often significant effort has been contributed to
+ * find and fix important bugs and other problems to
+ * improve the reliability of the library, which sometimes
+ * is not reflected in the amount of code which changed as
+ * result.
+ * As much as possible, the contributors are acknowledged
+ * in the ChangeLog file in the source code distribution
+ * where their changes are noted in detail.
+ *
+ * Contributors are listed in the CONTRIBUTORS file.
+ *
+ * As usual, all bouquets go to the contributors, and all
+ * brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ * The code base for this project is coordinated and
+ * eventually pre-tested, packaged, and made available by
+ *
+ * Ross Johnson <rpj@callisto.canberra.edu.au>
+ *
+ * QA Testers:
+ * Ultimately, the library is tested in the real world by
+ * a host of competent and demanding scientists and
+ * engineers who report bugs and/or provide solutions
+ * which are then fixed or incorporated into subsequent
+ * versions of the library. Each time a bug is fixed, a
+ * test case is written to prove the fix and ensure
+ * that later changes to the code don't reintroduce the
+ * same error. The number of test cases is slowly growing
+ * and therefore so is the code reliability.
+ *
+ * Compliance:
+ * See the file ANNOUNCE for the list of implemented
+ * and not-implemented routines and defined options.
+ * Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ * The source code and other information about this library
+ * are available from
+ *
+ * http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
+/*
+ * VC++6.0 or early compiler's header has no DWORD_PTR type.
+ */
+typedef unsigned long DWORD_PTR;
+#endif
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifndef NEED_FTIME
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <setjmp.h>
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+ PTW32_FALSE = 0,
+ PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define some error numbers.
+ */
+#ifndef ENOTSUP
+# define ENOTSUP 48 /* This is the value in Solaris. */
+#endif
+
+#ifndef ETIMEDOUT
+# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
+#endif
+
+#ifndef ENOSYS
+# define ENOSYS 140 /* Semi-arbitrary value */
+#endif
+
+#ifndef EDEADLK
+# ifdef EDEADLOCK
+# define EDEADLK EDEADLOCK
+# else
+# define EDEADLK 36 /* This is the value in MSVC. */
+# endif
+#endif
+
+#include "sched.h"
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it.
+ */
+#ifndef PTW32_INCLUDE_WINDOWS_H
+#ifndef HANDLE
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#ifndef DWORD
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#ifndef HAVE_STRUCT_TIMESPEC
+#define HAVE_STRUCT_TIMESPEC 1
+struct timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#ifndef SIG_UNBLOCK
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * Options are normally set in <unistd.h>, which is not provided
+ * with pthreads-win32.
+ *
+ * For conformance with the Single Unix Specification (version 3), all of the
+ * options below are defined, and have a value of either -1 (not supported)
+ * or 200112L (supported).
+ *
+ * These options can neither be left undefined nor have a value of 0, because
+ * either indicates that sysconf(), which is not implemented, may be used at
+ * runtime to check the status of the option.
+ *
+ * _POSIX_THREADS (== 200112L)
+ * If == 200112L, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
+ * If == 200112L, you can control the size of a thread's
+ * stack
+ * pthread_attr_getstacksize
+ * pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (== -1)
+ * If == 200112L, you can allocate and control a thread's
+ * stack. If not supported, the following functions
+ * will return ENOSYS, indicating they are not
+ * supported:
+ * pthread_attr_getstackaddr
+ * pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
+ * If == 200112L, you can use realtime scheduling.
+ * This option indicates that the behaviour of some
+ * implemented functions conforms to the additional TPS
+ * requirements in the standard. E.g. rwlocks favour
+ * writers over readers when threads have equal priority.
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (== -1)
+ * If == 200112L, you can create priority inheritance
+ * mutexes.
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (== -1)
+ * If == 200112L, you can create priority ceiling mutexes
+ * Indicates the availability of:
+ * pthread_mutex_getprioceiling
+ * pthread_mutex_setprioceiling
+ * pthread_mutexattr_getprioceiling
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprioceiling
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (== -1)
+ * If set, you can create mutexes and condition
+ * variables that can be shared with another
+ * process.If set, indicates the availability
+ * of:
+ * pthread_mutexattr_getpshared
+ * pthread_mutexattr_setpshared
+ * pthread_condattr_getpshared
+ * pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
+ * If == 200112L you can use the special *_r library
+ * functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (== 200112L)
+ * If == 200112L, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (== 200112L)
+ * If == 200112L, you can use spin locks
+ *
+ * _POSIX_BARRIERS (== 200112L)
+ * If == 200112L, you can use barriers
+ *
+ * + These functions provide both 'inherit' and/or
+ * 'protect' protocol, based upon these macro
+ * settings.
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#undef _POSIX_THREADS
+#define _POSIX_THREADS 200112L
+
+#undef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS 200112L
+
+#undef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS 200112L
+
+#undef _POSIX_BARRIERS
+#define _POSIX_BARRIERS 200112L
+
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
+
+#undef _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
+
+/*
+ * The following options are not supported
+ */
+#undef _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+#undef _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_INHERIT -1
+
+#undef _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PRIO_PROTECT -1
+
+/* TPS is not fully supported. */
+#undef _POSIX_THREAD_PRIORITY_SCHEDULING
+#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
+
+#undef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+
+
+/*
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * These limits are normally set in <limits.h>, which is not provided with
+ * pthreads-win32.
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Maximum number of attempts to destroy
+ * a thread's thread-specific data on
+ * termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ * Maximum number of thread-specific data keys
+ * available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ * Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ * Maximum number of threads supported per
+ * process (must be at least 64).
+ *
+ * SEM_NSEMS_MAX
+ * The maximum number of semaphores a process can have.
+ * (must be at least 256)
+ *
+ * SEM_VALUE_MAX
+ * The maximum value a semaphore can have.
+ * (must be at least 32767)
+ *
+ */
+#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+
+#undef PTHREAD_DESTRUCTOR_ITERATIONS
+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+#undef _POSIX_THREAD_KEYS_MAX
+#define _POSIX_THREAD_KEYS_MAX 128
+
+#undef PTHREAD_KEYS_MAX
+#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
+
+#undef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN 0
+
+#undef _POSIX_THREAD_THREADS_MAX
+#define _POSIX_THREAD_THREADS_MAX 64
+
+ /* Arbitrary value */
+#undef PTHREAD_THREADS_MAX
+#define PTHREAD_THREADS_MAX 2019
+
+#undef _POSIX_SEM_NSEMS_MAX
+#define _POSIX_SEM_NSEMS_MAX 256
+
+ /* Arbitrary value */
+#undef SEM_NSEMS_MAX
+#define SEM_NSEMS_MAX 1024
+
+#undef _POSIX_SEM_VALUE_MAX
+#define _POSIX_SEM_VALUE_MAX 32767
+
+#undef SEM_VALUE_MAX
+#define SEM_VALUE_MAX INT_MAX
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+# ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * The Open Watcom C/C++ compiler uses a non-standard calling convention
+ * that passes function args in registers unless __cdecl is explicitly specified
+ * in exposed function prototypes.
+ *
+ * We force all calls to cdecl even though this could slow Watcom code down
+ * slightly. If you know that the Watcom compiler will be used to build both
+ * the DLL and application, then you can probably define this as a null string.
+ * Remember that pthread.h (this file) is used for both the DLL and application builds.
+ */
+#define PTW32_CDECL __cdecl
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+# include <sys/types.h>
+#else
+/*
+ * Generic handle type - intended to extend uniqueness beyond
+ * that available with a simple pointer. It should scale for either
+ * IA-32 or IA-64.
+ */
+typedef struct {
+ void * p; /* Pointer to actual object */
+ unsigned int x; /* Extra information - reuse count etc */
+} ptw32_handle_t;
+
+typedef ptw32_handle_t pthread_t;
+typedef struct pthread_attr_t_ * pthread_attr_t;
+typedef struct pthread_once_t_ pthread_once_t;
+typedef struct pthread_key_t_ * pthread_key_t;
+typedef struct pthread_mutex_t_ * pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
+typedef struct pthread_cond_t_ * pthread_cond_t;
+typedef struct pthread_condattr_t_ * pthread_condattr_t;
+#endif
+typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
+typedef struct pthread_barrier_t_ * pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+ PTHREAD_CREATE_JOINABLE = 0, /* Default */
+ PTHREAD_CREATE_DETACHED = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+ PTHREAD_INHERIT_SCHED = 0,
+ PTHREAD_EXPLICIT_SCHED = 1, /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+ PTHREAD_SCOPE_PROCESS = 0,
+ PTHREAD_SCOPE_SYSTEM = 1, /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+ PTHREAD_CANCEL_ENABLE = 0, /* Default */
+ PTHREAD_CANCEL_DISABLE = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+ PTHREAD_CANCEL_ASYNCHRONOUS = 0,
+ PTHREAD_CANCEL_DEFERRED = 1, /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+ PTHREAD_PROCESS_PRIVATE = 0,
+ PTHREAD_PROCESS_SHARED = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+ PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
+
+struct pthread_once_t_
+{
+ int done; /* indicates if user function has been executed */
+ void * lock;
+ int reserved1;
+ int reserved2;
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
+
+/*
+ * Compatibility with LinuxThreads
+ */
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+ /* Compatibility with LinuxThreads */
+ PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+ /* For compatibility with POSIX */
+ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+
+#if defined(_MSC_VER)
+/* Disable MSVC 'anachronism used' warning */
+#pragma warning( disable : 4229 )
+#endif
+
+typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
+
+#if defined(_MSC_VER)
+#pragma warning( default : 4229 )
+#endif
+
+struct ptw32_cleanup_t
+{
+ ptw32_cleanup_callback_t routine;
+ void *arg;
+ struct ptw32_cleanup_t *prev;
+};
+
+#ifdef __CLEANUP_SEH
+ /*
+ * WIN32 SEH version of cancel cleanup.
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
+ _cleanup.arg = (_arg); \
+ __try \
+ { \
+
+#define pthread_cleanup_pop( _execute ) \
+ } \
+ __finally \
+ { \
+ if( _execute || AbnormalTermination()) \
+ { \
+ (*(_cleanup.routine))( _cleanup.arg ); \
+ } \
+ } \
+ }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+ /*
+ * C implementation of PThreads cancel cleanup
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+ (void) ptw32_pop_cleanup( _execute ); \
+ }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+ /*
+ * C++ version of cancel cleanup.
+ * - John E. Bossom.
+ */
+
+ class PThreadCleanup {
+ /*
+ * PThreadCleanup
+ *
+ * Purpose
+ * This class is a C++ helper class that is
+ * used to implement pthread_cleanup_push/
+ * pthread_cleanup_pop.
+ * The destructor of this class automatically
+ * pops the pushed cleanup routine regardless
+ * of how the code exits the scope
+ * (i.e. such as by an exception)
+ */
+ ptw32_cleanup_callback_t cleanUpRout;
+ void * obj;
+ int executeIt;
+
+ public:
+ PThreadCleanup() :
+ cleanUpRout( 0 ),
+ obj( 0 ),
+ executeIt( 0 )
+ /*
+ * No cleanup performed
+ */
+ {
+ }
+
+ PThreadCleanup(
+ ptw32_cleanup_callback_t routine,
+ void * arg ) :
+ cleanUpRout( routine ),
+ obj( arg ),
+ executeIt( 1 )
+ /*
+ * Registers a cleanup routine for 'arg'
+ */
+ {
+ }
+
+ ~PThreadCleanup()
+ {
+ if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+ {
+ (void) (*cleanUpRout)( obj );
+ }
+ }
+
+ void execute( int exec )
+ {
+ executeIt = exec;
+ }
+ };
+
+ /*
+ * C++ implementation of PThreads cancel cleanup;
+ * This implementation takes advantage of a helper
+ * class who's destructor automatically calls the
+ * cleanup routine if we exit our scope weirdly
+ */
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
+ (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+ cleanup.execute( _execute ); \
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
+ int *detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
+ void **stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
+ size_t * stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
+ int detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
+ void *stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
+ size_t stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *,
+ int *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
+ int inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr,
+ int * inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
+ int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
+ const pthread_attr_t * attr,
+ void *(*start) (void *),
+ void *arg);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
+ pthread_t t2);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
+ void **value_ptr);
+
+PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
+ int *oldstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
+ int *oldtype);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
+ void (*init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+ void (*routine) (void *),
+ void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
+ void (*destructor) (void *));
+
+PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
+ const void *value);
+
+PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+ int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
+ const pthread_barrierattr_t * attr,
+ unsigned int count);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
+ int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
+ const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
+ int policy,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
+ int *policy,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
+ const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+ int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+ int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+ int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
+
+/*
+ * Features that are auto-detected at load/run time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
+enum ptw32_features {
+ PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
+ PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
+};
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ * WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
+ DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#ifndef _UWIN
+# if defined(NEED_ERRNO)
+ PTW32_DLLPORT int * PTW32_CDECL _errno( void );
+# else
+# ifndef errno
+# if (defined(_MT) || defined(_DLL))
+ __declspec(dllimport) extern int * __cdecl _errno(void);
+# define errno (*_errno())
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * WIN32 C runtime library had been made thread-safe
+ * without affecting the user interface. Provide
+ * mappings from the UNIX thread-safe versions to
+ * the standard C runtime library calls.
+ * Only provide function mappings for functions that
+ * actually exist on WIN32.
+ */
+
+#if !defined(__MINGW32__)
+#define strtok_r( _s, _sep, _lasts ) \
+ ( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+#define asctime_r( _tm, _buf ) \
+ ( strcpy( (_buf), asctime( (_tm) ) ), \
+ (_buf) )
+
+#define ctime_r( _clock, _buf ) \
+ ( strcpy( (_buf), ctime( (_clock) ) ), \
+ (_buf) )
+
+#define gmtime_r( _clock, _result ) \
+ ( *(_result) = *gmtime( (_clock) ), \
+ (_result) )
+
+#define localtime_r( _clock, _result ) \
+ ( *(_result) = *localtime( (_clock) ), \
+ (_result) )
+
+#define rand_r( _seed ) \
+ ( _seed == _seed? rand() : rand() )
+
+
+/*
+ * Some compiler environments don't define some things.
+ */
+#if defined(__BORLANDC__)
+# define _ftime ftime
+# define _timeb timeb
+#endif
+
+#ifdef __cplusplus
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef PTW32_BUILD
+
+#ifdef __CLEANUP_SEH
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+ __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+ ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_CXX
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#ifdef _MSC_VER
+ /*
+ * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+ * if you want Pthread-Win32 cancelation and pthread_exit to work.
+ */
+
+#ifndef PtW32NoCatchWarn
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message(" cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message(" #ifdef PtW32CatchAll")
+#pragma message(" PtW32CatchAll")
+#pragma message(" #else")
+#pragma message(" catch(...)")
+#pragma message(" #endif")
+#pragma message(" {")
+#pragma message(" /* Catchall block processing */")
+#pragma message(" }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+ catch( ptw32_exception & ) { throw; } \
+ catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+ catch( ptw32_exception & ) { throw; } \
+ catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#ifdef PTW32__HANDLE_DEF
+# undef HANDLE
+#endif
+#ifdef PTW32__DWORD_DEF
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* ! RC_INVOKED */
+
+#endif /* PTHREAD_H */
--- /dev/null
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ * Provides an implementation of POSIX realtime extensions
+ * as defined in
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef _SCHED_H
+#define _SCHED_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+# ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if defined(__MINGW32__) || defined(_UWIN)
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+/* For pid_t */
+# include <sys/types.h>
+/* Required by Unix 98 */
+# include <time.h>
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+#else
+typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+ SCHED_OTHER = 0,
+ SCHED_FIFO,
+ SCHED_RR,
+ SCHED_MIN = SCHED_OTHER,
+ SCHED_MAX = SCHED_RR
+};
+
+struct sched_param {
+ int sched_priority;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+PTW32_DLLPORT int __cdecl sched_yield (void);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+ ( errno = ENOTSUP, (int) -1 )
+
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* !_SCHED_H */
+
--- /dev/null
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+# ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#define _POSIX_SEMAPHORES
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifndef HAVE_MODE_T
+typedef unsigned int mode_t;
+#endif
+
+
+typedef struct sem_t_ * sem_t;
+
+PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
+ int pshared,
+ unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
+ const struct timespec * abstime);
+
+PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
+ int count);
+
+PTW32_DLLPORT int __cdecl sem_open (const char * name,
+ int oflag,
+ mode_t mode,
+ unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
+
+PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
+ int * sval);
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* !SEMAPHORE_H */
--- /dev/null
+#pragma once
+
+/*
+ * boblight
+ * Copyright (C) Bob 2009
+ *
+ * boblight is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * boblight is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "os-dependent.h"
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+#ifndef __WINDOWS__
+#include <termios.h>
+#else
+#include "../util/threads.h"
+#include "../util/buffer.h"
+
+class CSerialPort;
+
+typedef struct serial_cancel_options
+{
+ CSerialPort *instance;
+ uint64_t iWaitMs;
+} serial_cancel_options;
+
+#endif
+
+#define PAR_NONE 0
+#define PAR_EVEN 1
+#define PAR_ODD 2
+
+#include "baudrate.h"
+
+class CSerialPort
+{
+ public:
+ CSerialPort();
+ virtual ~CSerialPort();
+
+ bool Open(std::string name, int baudrate, int databits = 8, int stopbits = 1, int parity = PAR_NONE);
+ void Close();
+ int Write(std::vector<uint8_t> data)
+ {
+ return Write(&data[0], data.size());
+ }
+
+ int Write(uint8_t* data, int len);
+ int Read(uint8_t* data, int len, int iTimeoutMs = -1);
+
+ std::string GetError() { return m_name + ": " + m_error; }
+ std::string GetName() { return m_name; }
+
+ bool SetBaudRate(int baudrate);
+
+ int IntToRate(int baudrate)
+ {
+ for (unsigned int i = 0; i < sizeof(baudrates) / sizeof(sbaudrate) - 1; i++)
+ {
+ if (baudrates[i].rate == baudrate)
+ {
+ return baudrates[i].symbol;
+ }
+ }
+ return -1;
+ };
+
+#ifdef __WINDOWS__
+ bool IsOpen() const { return m_bIsOpen; }
+#else
+ bool IsOpen() const { return m_fd != -1; }
+#endif
+
+private:
+ std::string m_error;
+ std::string m_name;
+
+#ifdef __WINDOWS__
+ bool SetTimeouts(bool bBlocking);
+
+ HANDLE m_handle;
+ bool m_bIsOpen;
+ int m_iBaudrate;
+ int m_iDatabits;
+ int m_iStopbits;
+ int m_iParity;
+ int64_t m_iTimeout;
+ CecBuffer<uint8_t> m_buffer;
+ HANDLE m_ovHandle;
+#else
+ struct termios m_options;
+ int m_fd;
+#endif
+};
--- /dev/null
+/*
+ * dlfcn-win32
+ * Copyright (c) 2007 Ramiro Polla
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "dlfcn-win32.h"
+
+/* Note:
+ * MSDN says these functions are not thread-safe. We make no efforts to have
+ * any kind of thread safety.
+ */
+
+/* I have no special reason to have set MAX_GLOBAL_OBJECTS to this value. Any
+ * comments are welcome.
+ */
+#define MAX_OBJECTS 255
+
+static HMODULE global_objects[MAX_OBJECTS];
+
+/* This function adds an object to the list of global objects.
+ * The implementation is very simple and slow.
+ * TODO: should failing this function be enough to fail the call to dlopen( )?
+ */
+static void global_object_add( HMODULE hModule )
+{
+ int i;
+
+ for( i = 0 ; i < MAX_OBJECTS ; i++ )
+ {
+ if( !global_objects[i] )
+ {
+ global_objects[i] = hModule;
+ break;
+ }
+ }
+}
+
+static void global_object_rem( HMODULE hModule )
+{
+ int i;
+
+ for( i = 0 ; i < MAX_OBJECTS ; i++ )
+ {
+ if( global_objects[i] == hModule )
+ {
+ global_objects[i] = 0;
+ break;
+ }
+ }
+}
+
+/* Argument to last function. Used in dlerror( ) */
+static char last_name[MAX_PATH];
+
+static int copy_string( char *dest, int dest_size, const char *src )
+{
+ int i = 0;
+
+ if( src && dest )
+ {
+ for( i = 0 ; i < dest_size-1 ; i++ )
+ {
+ if( !src[i] )
+ break;
+ else
+ dest[i] = src[i];
+ }
+ }
+ dest[i] = '\0';
+
+ return i;
+}
+
+void *dlopen( const char *file, int mode )
+{
+ HMODULE hModule;
+ UINT uMode;
+
+ /* Do not let Windows display the critical-error-handler message box */
+ uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
+
+ if( file == 0 )
+ {
+ /* Save NULL pointer for error message */
+ _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", file );
+
+ /* POSIX says that if the value of file is 0, a handle on a global
+ * symbol object must be provided. That object must be able to access
+ * all symbols from the original program file, and any objects loaded
+ * with the RTLD_GLOBAL flag.
+ * The return value from GetModuleHandle( ) allows us to retrieve
+ * symbols only from the original program file. For objects loaded with
+ * the RTLD_GLOBAL flag, we create our own list later on.
+ */
+ hModule = GetModuleHandle( NULL );
+ }
+ else
+ {
+ char lpFileName[MAX_PATH];
+ int i;
+
+ /* MSDN says backslashes *must* be used instead of forward slashes. */
+ for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ )
+ {
+ if( !file[i] )
+ break;
+ else if( file[i] == '/' )
+ lpFileName[i] = '\\';
+ else
+ lpFileName[i] = file[i];
+ }
+ lpFileName[i] = '\0';
+
+ /* Save file name for error message */
+ copy_string( last_name, sizeof(last_name), lpFileName );
+
+ /* POSIX says the search path is implementation-defined.
+ * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
+ * to UNIX's search paths (start with system folders instead of current
+ * folder).
+ */
+ hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH );
+ /* If the object was loaded with RTLD_GLOBAL, add it to list of global
+ * objects, so that its symbols may be retrieved even if the handle for
+ * the original program file is passed. POSIX says that if the same
+ * file is specified in multiple invocations, and any of them are
+ * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
+ * symbols will remain global.
+ */
+
+ if( hModule && (mode & RTLD_GLOBAL) )
+ global_object_add( hModule );
+ }
+
+ /* Return to previous state of the error-mode bit flags. */
+ SetErrorMode( uMode );
+
+ return (void *) hModule;
+}
+
+int dlclose( void *handle )
+{
+ HMODULE hModule = (HMODULE) handle;
+ BOOL ret;
+
+ /* Save handle for error message */
+ _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", handle );
+
+ ret = FreeLibrary( hModule );
+
+ /* If the object was loaded with RTLD_GLOBAL, remove it from list of global
+ * objects.
+ */
+ if( ret )
+ global_object_rem( hModule );
+
+ /* dlclose's return value in inverted in relation to FreeLibrary's. */
+ ret = !ret;
+
+ return (int) ret;
+}
+
+void *dlsym( void *handle, const char *name )
+{
+ FARPROC symbol;
+ HMODULE myhandle = (HMODULE) handle;
+
+ /* Save symbol name for error message */
+ copy_string( last_name, sizeof(last_name), name );
+
+ symbol = GetProcAddress( myhandle, name );
+#if 0
+ if( symbol == NULL )
+ {
+ HMODULE hModule;
+
+ /* If the handle for the original program file is passed, also search
+ * in all globally loaded objects.
+ */
+
+ hModule = GetModuleHandle( NULL );
+
+ if( hModule == handle )
+ {
+ int i;
+
+ for( i = 0 ; i < MAX_OBJECTS ; i++ )
+ {
+ if( global_objects[i] != 0 )
+ {
+ symbol = GetProcAddress( global_objects[i], name );
+ if( symbol != NULL )
+ break;
+ }
+ }
+ }
+
+
+ CloseHandle( hModule );
+ }
+#endif
+ return (void*) symbol;
+}
+
+char *dlerror( void )
+{
+ DWORD dwMessageId;
+ /* POSIX says this function doesn't have to be thread-safe, so we use one
+ * static buffer.
+ * MSDN says the buffer cannot be larger than 64K bytes, so we set it to
+ * the limit.
+ */
+ static char lpBuffer[65535];
+ DWORD ret;
+
+ dwMessageId = GetLastError( );
+
+ if( dwMessageId == 0 )
+ return NULL;
+
+ /* Format error message to:
+ * "<argument to function that failed>": <Windows localized error message>
+ */
+ ret = copy_string( lpBuffer, sizeof(lpBuffer), "\"" );
+ ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, last_name );
+ ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, "\": " );
+ ret += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId,
+ MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
+ lpBuffer+ret, sizeof(lpBuffer)-ret, NULL );
+
+ if( ret > 1 )
+ {
+ /* POSIX says the string must not have trailing <newline> */
+ if( lpBuffer[ret-2] == '\r' && lpBuffer[ret-1] == '\n' )
+ lpBuffer[ret-2] = '\0';
+ }
+
+ /* POSIX says that invoking dlerror( ) a second time, immediately following
+ * a prior invocation, shall result in NULL being returned.
+ */
+ SetLastError(0);
+
+ return lpBuffer;
+}
+
--- /dev/null
+#pragma once
+/*
+ * dlfcn-win32
+ * Copyright (c) 2007 Ramiro Polla
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef DLFCN_H
+#define DLFCN_H
+
+/* POSIX says these are implementation-defined.
+ * To simplify use with Windows API, we treat them the same way.
+ */
+
+#define RTLD_LAZY 0
+#define RTLD_NOW 0
+
+#define RTLD_GLOBAL (1 << 1)
+#define RTLD_LOCAL (1 << 2)
+
+/* These two were added in The Open Group Base Specifications Issue 6.
+ * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant.
+ */
+
+#define RTLD_DEFAULT 0
+#define RTLD_NEXT 0
+
+void *dlopen ( const char *file, int mode );
+int dlclose( void *handle );
+void *dlsym ( void *handle, const char *name );
+char *dlerror( void );
+
+#endif /* DLFCN-WIN32_H */
--- /dev/null
+/*
+ * Copyright (C) 2005-2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "os_windows.h"
+#include <sys/timeb.h>
+
+int gettimeofday(struct timeval *pcur_time, struct timezone *tz)
+{
+ if (pcur_time == NULL)
+ {
+ SetLastError(EFAULT);
+ return -1;
+ }
+ struct _timeb current;
+
+ _ftime(¤t);
+
+ pcur_time->tv_sec = (long) current.time;
+ pcur_time->tv_usec = current.millitm * 1000L;
+ if (tz)
+ {
+ tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */
+ tz->tz_dsttime = current.dstflag; /* type of dst correction */
+ }
+ return 0;
+}
--- /dev/null
+#pragma once
+/*
+ * Copyright (C) 2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#pragma warning(disable:4005) // Disable "warning C4005: '_WINSOCKAPI_' : macro redefinition"
+#include <winsock2.h>
+#pragma warning(default:4005)
+
+#include "../pthread_win32/pthread.h"
+
+#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
+# define __USE_FILE_OFFSET64 1
+#endif
+
+typedef signed __int32 int32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+
+#if defined __USE_FILE_OFFSET64
+typedef int64_t off_t;
+typedef uint64_t ino_t;
+#endif
+
+#define usleep(t) Sleep((t)/1000)
+#define snprintf _snprintf
+
+#include <stddef.h>
+#include <process.h>
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+#pragma warning (push)
+#endif
+/* prevent inclusion of wingdi.h */
+#define NOGDI
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+#pragma warning (pop)
+#endif
+#include <io.h>
+#include <stdlib.h>
+#include <errno.h>
+
+struct timezone
+{
+ int tz_minuteswest; /* minutes west of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+/*!
+ \brief implements similar unix call under windows
+ \return 0 on success, -1 on failure (if pcur_time was NULL)
+ \param pcur_time points to a timeval structure, should not be NULL
+ \param tz points to a timezone structure, may be NULL
+ */
+extern int gettimeofday(struct timeval *pcur_time, struct timezone *tz);
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "../serialport.h"
+#include "../baudrate.h"
+#include "../../util/timeutils.h"
+
+using namespace std;
+
+void FormatWindowsError(int iErrorCode, string &strMessage)
+{
+ if (iErrorCode != ERROR_SUCCESS)
+ {
+ char strAddMessage[1024];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, iErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), strAddMessage, 1024, NULL);
+ strMessage.append(": ");
+ strMessage.append(strAddMessage);
+ }
+}
+
+CSerialPort::CSerialPort(void) :
+ m_handle(INVALID_HANDLE_VALUE),
+ m_bIsOpen(false),
+ m_iBaudrate(0),
+ m_iDatabits(0),
+ m_iStopbits(0),
+ m_iParity(0)
+{
+}
+
+CSerialPort::~CSerialPort(void)
+{
+ Close();
+}
+
+bool CSerialPort::Open(string name, int baudrate, int databits, int stopbits, int parity)
+{
+ m_handle = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (m_handle == INVALID_HANDLE_VALUE)
+ {
+ m_error = "Unable to open COM port";
+ FormatWindowsError(GetLastError(), m_error);
+ return false;
+ }
+
+ COMMCONFIG commConfig = {0};
+ DWORD dwSize = sizeof(commConfig);
+ commConfig.dwSize = dwSize;
+ if (GetDefaultCommConfig(name.c_str(), &commConfig,&dwSize))
+ {
+ if (!SetCommConfig(m_handle, &commConfig,dwSize))
+ {
+ m_error = "unable to set default config";
+ FormatWindowsError(GetLastError(), m_error);
+ }
+ }
+ else
+ {
+ m_error = "unable to get default config";
+ FormatWindowsError(GetLastError(), m_error);
+ }
+
+ if (!SetupComm(m_handle, 64, 64))
+ {
+ m_error = "unable to set up the com port";
+ FormatWindowsError(GetLastError(), m_error);
+ }
+
+ m_iDatabits = databits;
+ m_iStopbits = stopbits;
+ m_iParity = parity;
+ if (!SetBaudRate(baudrate))
+ {
+ m_error = "unable to set baud rate";
+ FormatWindowsError(GetLastError(), m_error);
+ Close();
+ return false;
+ }
+
+ if (!SetTimeouts(false))
+ {
+ m_error = "unable to set timeouts";
+ FormatWindowsError(GetLastError(), m_error);
+ Close();
+ return false;
+ }
+
+ m_bIsOpen = true;
+ return m_bIsOpen;
+}
+
+bool CSerialPort::SetTimeouts(bool bBlocking)
+{
+ if (m_handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ COMMTIMEOUTS cto;
+ if (!GetCommTimeouts(m_handle, &cto))
+ {
+ m_error = "GetCommTimeouts failed";
+ FormatWindowsError(GetLastError(), m_error);
+ return false;
+ }
+
+ if (bBlocking)
+ {
+ cto.ReadIntervalTimeout = 0;
+ cto.ReadTotalTimeoutConstant = 0;
+ cto.ReadTotalTimeoutMultiplier = 0;
+ }
+ else
+ {
+ cto.ReadIntervalTimeout = MAXDWORD;
+ cto.ReadTotalTimeoutConstant = 0;
+ cto.ReadTotalTimeoutMultiplier = 0;
+ }
+
+ if (!SetCommTimeouts(m_handle, &cto))
+ {
+ m_error = "SetCommTimeouts failed";
+ FormatWindowsError(GetLastError(), m_error);
+ return false;
+ }
+
+ return true;
+}
+
+void CSerialPort::Close(void)
+{
+ if (m_bIsOpen)
+ {
+ CloseHandle(m_handle);
+ m_bIsOpen = false;
+ }
+}
+
+int CSerialPort::Write(uint8_t* data, int len)
+{
+ DWORD iBytesWritten = 0;
+ if (!m_bIsOpen)
+ return -1;
+
+ if (!WriteFile(m_handle, data, len, &iBytesWritten, NULL))
+ {
+ m_error = "Error while writing to COM port";
+ FormatWindowsError(GetLastError(), m_error);
+ return -1;
+ }
+
+ return (int) iBytesWritten;
+}
+
+int CSerialPort::Read(uint8_t* data, int len, int iTimeoutMs /* = -1 */)
+{
+ DWORD iBytesRead = 0;
+ if (m_handle == 0)
+ {
+ m_error = "Error while reading from COM port: invalid handle";
+ return -1;
+ }
+
+ if(!ReadFile(m_handle, data, len, &iBytesRead, NULL) != 0)
+ {
+ m_error = "unable to read from device";
+ FormatWindowsError(GetLastError(), m_error);
+ iBytesRead = -1;
+ }
+
+ return (int) iBytesRead;
+}
+
+bool CSerialPort::SetBaudRate(int baudrate)
+{
+ m_iBaudrate = baudrate;
+
+ DCB dcb;
+ memset(&dcb,0,sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ dcb.BaudRate = IntToRate(m_iBaudrate);
+ dcb.fBinary = true;
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
+ dcb.fRtsControl = RTS_CONTROL_DISABLE;
+ dcb.fOutxCtsFlow = false;
+ dcb.fOutxDsrFlow = false;
+ dcb.fOutX = false;
+ dcb.fInX = false;
+ dcb.fAbortOnError = true;
+
+ if (m_iParity == PAR_NONE)
+ dcb.Parity = NOPARITY;
+ else if (m_iParity == PAR_EVEN)
+ dcb.Parity = EVENPARITY;
+ else
+ dcb.Parity = ODDPARITY;
+
+ if (m_iStopbits == 2)
+ dcb.StopBits = TWOSTOPBITS;
+ else
+ dcb.StopBits = ONESTOPBIT;
+
+ dcb.ByteSize = m_iDatabits;
+
+ if(!SetCommState(m_handle,&dcb))
+ {
+ m_error = "SetCommState failed";
+ FormatWindowsError(GetLastError(), m_error);
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libcec
+Description: CEC interface library
+URL: http://www.pulse-eight.com/
+Version: @VERSION@
+Requires: udev
+Libs: -L${libdir} -lcec
+Cflags: -I${includedir}
--- /dev/null
+#pragma once
+#include <string>
+#include <stdint.h>
+#include <vector>
+
+#if defined(_WIN32) && !defined(va_copy)
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+
+// =============================================================================
+// FILE: StdString.h
+// AUTHOR: Joe O'Leary (with outside help noted in comments)
+//
+// If you find any bugs in this code, please let me know:
+//
+// jmoleary@earthlink.net
+// http://www.joeo.net/stdstring.htm (a bit outdated)
+//
+// The latest version of this code should always be available at the
+// following link:
+//
+// http://www.joeo.net/code/StdString.zip (Dec 6, 2003)
+//
+//
+// REMARKS:
+// This header file declares the CStdStr template. This template derives
+// the Standard C++ Library basic_string<> template and add to it the
+// the following conveniences:
+// - The full MFC CString set of functions (including implicit cast)
+// - writing to/reading from COM IStream interfaces
+// - Functional objects for use in STL algorithms
+//
+// From this template, we intstantiate two classes: CStdStringA and
+// CStdStringW. The name "CStdString" is just a #define of one of these,
+// based upone the UNICODE macro setting
+//
+// This header also declares our own version of the MFC/ATL UNICODE-MBCS
+// conversion macros. Our version looks exactly like the Microsoft's to
+// facilitate portability.
+//
+// NOTE:
+// If you you use this in an MFC or ATL build, you should include either
+// afx.h or atlbase.h first, as appropriate.
+//
+// PEOPLE WHO HAVE CONTRIBUTED TO THIS CLASS:
+//
+// Several people have helped me iron out problems and othewise improve
+// this class. OK, this is a long list but in my own defense, this code
+// has undergone two major rewrites. Many of the improvements became
+// necessary after I rewrote the code as a template. Others helped me
+// improve the CString facade.
+//
+// Anyway, these people are (in chronological order):
+//
+// - Pete the Plumber (???)
+// - Julian Selman
+// - Chris (of Melbsys)
+// - Dave Plummer
+// - John C Sipos
+// - Chris Sells
+// - Nigel Nunn
+// - Fan Xia
+// - Matthew Williams
+// - Carl Engman
+// - Mark Zeren
+// - Craig Watson
+// - Rich Zuris
+// - Karim Ratib
+// - Chris Conti
+// - Baptiste Lepilleur
+// - Greg Pickles
+// - Jim Cline
+// - Jeff Kohn
+// - Todd Heckel
+// - Ullrich Poll�hne
+// - Joe Vitaterna
+// - Joe Woodbury
+// - Aaron (no last name)
+// - Joldakowski (???)
+// - Scott Hathaway
+// - Eric Nitzche
+// - Pablo Presedo
+// - Farrokh Nejadlotfi
+// - Jason Mills
+// - Igor Kholodov
+// - Mike Crusader
+// - John James
+// - Wang Haifeng
+// - Tim Dowty
+// - Arnt Witteveen
+// - Glen Maynard
+// - Paul DeMarco
+// - Bagira (full name?)
+// - Ronny Schulz
+// - Jakko Van Hunen
+// - Charles Godwin
+// - Henk Demper
+// - Greg Marr
+// - Bill Carducci
+// - Brian Groose
+// - MKingman
+// - Don Beusee
+//
+// REVISION HISTORY
+//
+// 2005-JAN-10 - Thanks to Don Beusee for pointing out the danger in mapping
+// length-checked formatting functions to non-length-checked
+// CRT equivalents. Also thanks to him for motivating me to
+// optimize my implementation of Replace()
+//
+// 2004-APR-22 - A big, big thank you to "MKingman" (whoever you are) for
+// finally spotting a silly little error in StdCodeCvt that
+// has been causing me (and users of CStdString) problems for
+// years in some relatively rare conversions. I had reversed
+// two length arguments.
+//
+// 2003-NOV-24 - Thanks to a bunch of people for helping me clean up many
+// compiler warnings (and yes, even a couple of actual compiler
+// errors). These include Henk Demper for figuring out how
+// to make the Intellisense work on with CStdString on VC6,
+// something I was never able to do. Greg Marr pointed out
+// a compiler warning about an unreferenced symbol and a
+// problem with my version of Load in MFC builds. Bill
+// Carducci took a lot of time with me to help me figure out
+// why some implementations of the Standard C++ Library were
+// returning error codes for apparently successful conversions
+// between ASCII and UNICODE. Finally thanks to Brian Groose
+// for helping me fix compiler signed unsigned warnings in
+// several functions.
+//
+// 2003-JUL-10 - Thanks to Charles Godwin for making me realize my 'FmtArg'
+// fixes had inadvertently broken the DLL-export code (which is
+// normally commented out. I had to move it up higher. Also
+// this helped me catch a bug in ssicoll that would prevent
+// compilation, otherwise.
+//
+// 2003-MAR-14 - Thanks to Jakko Van Hunen for pointing out a copy-and-paste
+// bug in one of the overloads of FmtArg.
+//
+// 2003-MAR-10 - Thanks to Ronny Schulz for (twice!) sending me some changes
+// to help CStdString build on SGI and for pointing out an
+// error in placement of my preprocessor macros for ssfmtmsg.
+//
+// 2002-NOV-26 - Thanks to Bagira for pointing out that my implementation of
+// SpanExcluding was not properly handling the case in which
+// the string did NOT contain any of the given characters
+//
+// 2002-OCT-21 - Many thanks to Paul DeMarco who was invaluable in helping me
+// get this code working with Borland's free compiler as well
+// as the Dev-C++ compiler (available free at SourceForge).
+//
+// 2002-SEP-13 - Thanks to Glen Maynard who helped me get rid of some loud
+// but harmless warnings that were showing up on g++. Glen
+// also pointed out that some pre-declarations of FmtArg<>
+// specializations were unnecessary (and no good on G++)
+//
+// 2002-JUN-26 - Thanks to Arnt Witteveen for pointing out that I was using
+// static_cast<> in a place in which I should have been using
+// reinterpret_cast<> (the ctor for unsigned char strings).
+// That's what happens when I don't unit-test properly!
+// Arnt also noticed that CString was silently correcting the
+// 'nCount' argument to Left() and Right() where CStdString was
+// not (and crashing if it was bad). That is also now fixed!
+//
+// 2002-FEB-25 - Thanks to Tim Dowty for pointing out (and giving me the fix
+// for) a conversion problem with non-ASCII MBCS characters.
+// CStdString is now used in my favorite commercial MP3 player!
+//
+// 2001-DEC-06 - Thanks to Wang Haifeng for spotting a problem in one of the
+// assignment operators (for _bstr_t) that would cause compiler
+// errors when refcounting protection was turned off.
+//
+// 2001-NOV-27 - Remove calls to operator!= which involve reverse_iterators
+// due to a conflict with the rel_ops operator!=. Thanks to
+// John James for pointing this out.
+//
+// 2001-OCT-29 - Added a minor range checking fix for the Mid function to
+// make it as forgiving as CString's version is. Thanks to
+// Igor Kholodov for noticing this.
+// - Added a specialization of std::swap for CStdString. Thanks
+// to Mike Crusader for suggesting this! It's commented out
+// because you're not supposed to inject your own code into the
+// 'std' namespace. But if you don't care about that, it's
+// there if you want it
+// - Thanks to Jason Mills for catching a case where CString was
+// more forgiving in the Delete() function than I was.
+//
+// 2001-JUN-06 - I was violating the Standard name lookup rules stated
+// in [14.6.2(3)]. None of the compilers I've tried so
+// far apparently caught this but HP-UX aCC 3.30 did. The
+// fix was to add 'this->' prefixes in many places.
+// Thanks to Farrokh Nejadlotfi for this!
+//
+// 2001-APR-27 - StreamLoad was calculating the number of BYTES in one
+// case, not characters. Thanks to Pablo Presedo for this.
+//
+// 2001-FEB-23 - Replace() had a bug which caused infinite loops if the
+// source string was empty. Fixed thanks to Eric Nitzsche.
+//
+// 2001-FEB-23 - Scott Hathaway was a huge help in providing me with the
+// ability to build CStdString on Sun Unix systems. He
+// sent me detailed build reports about what works and what
+// does not. If CStdString compiles on your Unix box, you
+// can thank Scott for it.
+//
+// 2000-DEC-29 - Joldakowski noticed one overload of Insert failed to do a
+// range check as CString's does. Now fixed -- thanks!
+//
+// 2000-NOV-07 - Aaron pointed out that I was calling static member
+// functions of char_traits via a temporary. This was not
+// technically wrong, but it was unnecessary and caused
+// problems for poor old buggy VC5. Thanks Aaron!
+//
+// 2000-JUL-11 - Joe Woodbury noted that the CString::Find docs don't match
+// what the CString::Find code really ends up doing. I was
+// trying to match the docs. Now I match the CString code
+// - Joe also caught me truncating strings for GetBuffer() calls
+// when the supplied length was less than the current length.
+//
+// 2000-MAY-25 - Better support for STLPORT's Standard library distribution
+// - Got rid of the NSP macro - it interfered with Koenig lookup
+// - Thanks to Joe Woodbury for catching a TrimLeft() bug that
+// I introduced in January. Empty strings were not getting
+// trimmed
+//
+// 2000-APR-17 - Thanks to Joe Vitaterna for pointing out that ReverseFind
+// is supposed to be a const function.
+//
+// 2000-MAR-07 - Thanks to Ullrich Poll�hne for catching a range bug in one
+// of the overloads of assign.
+//
+// 2000-FEB-01 - You can now use CStdString on the Mac with CodeWarrior!
+// Thanks to Todd Heckel for helping out with this.
+//
+// 2000-JAN-23 - Thanks to Jim Cline for pointing out how I could make the
+// Trim() function more efficient.
+// - Thanks to Jeff Kohn for prompting me to find and fix a typo
+// in one of the addition operators that takes _bstr_t.
+// - Got rid of the .CPP file - you only need StdString.h now!
+//
+// 1999-DEC-22 - Thanks to Greg Pickles for helping me identify a problem
+// with my implementation of CStdString::FormatV in which
+// resulting string might not be properly NULL terminated.
+//
+// 1999-DEC-06 - Chris Conti pointed yet another basic_string<> assignment
+// bug that MS has not fixed. CStdString did nothing to fix
+// it either but it does now! The bug was: create a string
+// longer than 31 characters, get a pointer to it (via c_str())
+// and then assign that pointer to the original string object.
+// The resulting string would be empty. Not with CStdString!
+//
+// 1999-OCT-06 - BufferSet was erasing the string even when it was merely
+// supposed to shrink it. Fixed. Thanks to Chris Conti.
+// - Some of the Q172398 fixes were not checking for assignment-
+// to-self. Fixed. Thanks to Baptiste Lepilleur.
+//
+// 1999-AUG-20 - Improved Load() function to be more efficient by using
+// SizeOfResource(). Thanks to Rich Zuris for this.
+// - Corrected resource ID constructor, again thanks to Rich.
+// - Fixed a bug that occurred with UNICODE characters above
+// the first 255 ANSI ones. Thanks to Craig Watson.
+// - Added missing overloads of TrimLeft() and TrimRight().
+// Thanks to Karim Ratib for pointing them out
+//
+// 1999-JUL-21 - Made all calls to GetBuf() with no args check length first.
+//
+// 1999-JUL-10 - Improved MFC/ATL independence of conversion macros
+// - Added SS_NO_REFCOUNT macro to allow you to disable any
+// reference-counting your basic_string<> impl. may do.
+// - Improved ReleaseBuffer() to be as forgiving as CString.
+// Thanks for Fan Xia for helping me find this and to
+// Matthew Williams for pointing it out directly.
+//
+// 1999-JUL-06 - Thanks to Nigel Nunn for catching a very sneaky bug in
+// ToLower/ToUpper. They should call GetBuf() instead of
+// data() in order to ensure the changed string buffer is not
+// reference-counted (in those implementations that refcount).
+//
+// 1999-JUL-01 - Added a true CString facade. Now you can use CStdString as
+// a drop-in replacement for CString. If you find this useful,
+// you can thank Chris Sells for finally convincing me to give
+// in and implement it.
+// - Changed operators << and >> (for MFC CArchive) to serialize
+// EXACTLY as CString's do. So now you can send a CString out
+// to a CArchive and later read it in as a CStdString. I have
+// no idea why you would want to do this but you can.
+//
+// 1999-JUN-21 - Changed the CStdString class into the CStdStr template.
+// - Fixed FormatV() to correctly decrement the loop counter.
+// This was harmless bug but a bug nevertheless. Thanks to
+// Chris (of Melbsys) for pointing it out
+// - Changed Format() to try a normal stack-based array before
+// using to _alloca().
+// - Updated the text conversion macros to properly use code
+// pages and to fit in better in MFC/ATL builds. In other
+// words, I copied Microsoft's conversion stuff again.
+// - Added equivalents of CString::GetBuffer, GetBufferSetLength
+// - new sscpy() replacement of CStdString::CopyString()
+// - a Trim() function that combines TrimRight() and TrimLeft().
+//
+// 1999-MAR-13 - Corrected the "NotSpace" functional object to use _istpace()
+// instead of _isspace() Thanks to Dave Plummer for this.
+//
+// 1999-FEB-26 - Removed errant line (left over from testing) that #defined
+// _MFC_VER. Thanks to John C Sipos for noticing this.
+//
+// 1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that
+// caused infinite recursion and stack overflow
+// - Added member functions to simplify the process of
+// persisting CStdStrings to/from DCOM IStream interfaces
+// - Added functional objects (e.g. StdStringLessNoCase) that
+// allow CStdStrings to be used as keys STL map objects with
+// case-insensitive comparison
+// - Added array indexing operators (i.e. operator[]). I
+// originally assumed that these were unnecessary and would be
+// inherited from basic_string. However, without them, Visual
+// C++ complains about ambiguous overloads when you try to use
+// them. Thanks to Julian Selman to pointing this out.
+//
+// 1998-FEB-?? - Added overloads of assign() function to completely account
+// for Q172398 bug. Thanks to "Pete the Plumber" for this
+//
+// 1998-FEB-?? - Initial submission
+//
+// COPYRIGHT:
+// 2002 Joseph M. O'Leary. This code is 100% free. Use it anywhere you
+// want. Rewrite it, restructure it, whatever. If you can write software
+// that makes money off of it, good for you. I kinda like capitalism.
+// Please don't blame me if it causes your $30 billion dollar satellite
+// explode in orbit. If you redistribute it in any form, I'd appreciate it
+// if you would leave this notice here.
+// =============================================================================
+
+// Avoid multiple inclusion
+
+#ifndef STDSTRING_H
+#define STDSTRING_H
+
+// When using VC, turn off browser references
+// Turn off unavoidable compiler warnings
+
+#if defined(_MSC_VER) && (_MSC_VER > 1100)
+ #pragma component(browser, off, references, "CStdString")
+ #pragma warning (disable : 4290) // C++ Exception Specification ignored
+ #pragma warning (disable : 4127) // Conditional expression is constant
+ #pragma warning (disable : 4097) // typedef name used as synonym for class name
+#endif
+
+// Borland warnings to turn off
+
+#ifdef __BORLANDC__
+ #pragma option push -w-inl
+// #pragma warn -inl // Turn off inline function warnings
+#endif
+
+// SS_IS_INTRESOURCE
+// -----------------
+// A copy of IS_INTRESOURCE from VC7. Because old VC6 version of winuser.h
+// doesn't have this.
+
+#define SS_IS_INTRESOURCE(_r) (false)
+
+#if !defined (SS_ANSI) && defined(_MSC_VER)
+ #undef SS_IS_INTRESOURCE
+ #if defined(_WIN64)
+ #define SS_IS_INTRESOURCE(_r) (((unsigned __int64)(_r) >> 16) == 0)
+ #else
+ #define SS_IS_INTRESOURCE(_r) (((unsigned long)(_r) >> 16) == 0)
+ #endif
+#endif
+
+
+// MACRO: SS_UNSIGNED
+// ------------------
+// This macro causes the addition of a constructor and assignment operator
+// which take unsigned characters. CString has such functions and in order
+// to provide maximum CString-compatability, this code needs them as well.
+// In practice you will likely never need these functions...
+
+//#define SS_UNSIGNED
+
+#ifdef SS_ALLOW_UNSIGNED_CHARS
+ #define SS_UNSIGNED
+#endif
+
+// MACRO: SS_SAFE_FORMAT
+// ---------------------
+// This macro provides limited compatability with a questionable CString
+// "feature". You can define it in order to avoid a common problem that
+// people encounter when switching from CString to CStdString.
+//
+// To illustrate the problem -- With CString, you can do this:
+//
+// CString sName("Joe");
+// CString sTmp;
+// sTmp.Format("My name is %s", sName); // WORKS!
+//
+// However if you were to try this with CStdString, your program would
+// crash.
+//
+// CStdString sName("Joe");
+// CStdString sTmp;
+// sTmp.Format("My name is %s", sName); // CRASHES!
+//
+// You must explicitly call c_str() or cast the object to the proper type
+//
+// sTmp.Format("My name is %s", sName.c_str()); // WORKS!
+// sTmp.Format("My name is %s", static_cast<PCSTR>(sName));// WORKS!
+// sTmp.Format("My name is %s", (PCSTR)sName); // WORKS!
+//
+// This is because it is illegal to pass anything but a POD type as a
+// variadic argument to a variadic function (i.e. as one of the "..."
+// arguments). The type const char* is a POD type. The type CStdString
+// is not. Of course, neither is the type CString, but CString lets you do
+// it anyway due to the way they laid out the class in binary. I have no
+// control over this in CStdString since I derive from whatever
+// implementation of basic_string is available.
+//
+// However if you have legacy code (which does this) that you want to take
+// out of the MFC world and you don't want to rewrite all your calls to
+// Format(), then you can define this flag and it will no longer crash.
+//
+// Note however that this ONLY works for Format(), not sprintf, fprintf,
+// etc. If you pass a CStdString object to one of those functions, your
+// program will crash. Not much I can do to get around this, short of
+// writing substitutes for those functions as well.
+
+#define SS_SAFE_FORMAT // use new template style Format() function
+
+
+// MACRO: SS_NO_IMPLICIT_CAST
+// --------------------------
+// Some people don't like the implicit cast to const char* (or rather to
+// const CT*) that CStdString (and MFC's CString) provide. That was the
+// whole reason I created this class in the first place, but hey, whatever
+// bakes your cake. Just #define this macro to get rid of the the implicit
+// cast.
+
+//#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*()
+
+
+// MACRO: SS_NO_REFCOUNT
+// ---------------------
+// turns off reference counting at the assignment level. Only needed
+// for the version of basic_string<> that comes with Visual C++ versions
+// 6.0 or earlier, and only then in some heavily multithreaded scenarios.
+// Uncomment it if you feel you need it.
+
+//#define SS_NO_REFCOUNT
+
+// MACRO: SS_WIN32
+// ---------------
+// When this flag is set, we are building code for the Win32 platform and
+// may use Win32 specific functions (such as LoadString). This gives us
+// a couple of nice extras for the code.
+//
+// Obviously, Microsoft's is not the only compiler available for Win32 out
+// there. So I can't just check to see if _MSC_VER is defined to detect
+// if I'm building on Win32. So for now, if you use MS Visual C++ or
+// Borland's compiler, I turn this on. Otherwise you may turn it on
+// yourself, if you prefer
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32)
+ #define SS_WIN32
+#endif
+
+// MACRO: SS_ANSI
+// --------------
+// When this macro is defined, the code attempts only to use ANSI/ISO
+// standard library functions to do it's work. It will NOT attempt to use
+// any Win32 of Visual C++ specific functions -- even if they are
+// available. You may define this flag yourself to prevent any Win32
+// of VC++ specific functions from being called.
+
+// If we're not on Win32, we MUST use an ANSI build
+
+#ifndef SS_WIN32
+ #if !defined(SS_NO_ANSI)
+ #define SS_ANSI
+ #endif
+#endif
+
+// MACRO: SS_ALLOCA
+// ----------------
+// Some implementations of the Standard C Library have a non-standard
+// function known as alloca(). This functions allows one to allocate a
+// variable amount of memory on the stack. It is needed to implement
+// the ASCII/MBCS conversion macros.
+//
+// I wanted to find some way to determine automatically if alloca() is
+// available on this platform via compiler flags but that is asking for
+// trouble. The crude test presented here will likely need fixing on
+// other platforms. Therefore I'll leave it up to you to fiddle with
+// this test to determine if it exists. Just make sure SS_ALLOCA is or
+// is not defined as appropriate and you control this feature.
+
+#if defined(_MSC_VER) && !defined(SS_ANSI)
+ #define SS_ALLOCA
+#endif
+
+
+// MACRO: SS_MBCS
+// --------------
+// Setting this macro means you are using MBCS characters. In MSVC builds,
+// this macro gets set automatically by detection of the preprocessor flag
+// _MBCS. For other platforms you may set it manually if you wish. The
+// only effect it currently has is to cause the allocation of more space
+// for wchar_t --> char conversions.
+// Note that MBCS does not mean UNICODE.
+//
+// #define SS_MBCS
+//
+
+#ifdef _MBCS
+ #define SS_MBCS
+#endif
+
+
+// MACRO SS_NO_LOCALE
+// ------------------
+// If your implementation of the Standard C++ Library lacks the <locale> header,
+// you can #define this macro to make your code build properly. Note that this
+// is some of my newest code and frankly I'm not very sure of it, though it does
+// pass my unit tests.
+
+// #define SS_NO_LOCALE
+
+
+// Compiler Error regarding _UNICODE and UNICODE
+// -----------------------------------------------
+// Microsoft header files are screwy. Sometimes they depend on a preprocessor
+// flag named "_UNICODE". Other times they check "UNICODE" (note the lack of
+// leading underscore in the second version". In several places, they silently
+// "synchronize" these two flags this by defining one of the other was defined.
+// In older version of this header, I used to try to do the same thing.
+//
+// However experience has taught me that this is a bad idea. You get weird
+// compiler errors that seem to indicate things like LPWSTR and LPTSTR not being
+// equivalent in UNICODE builds, stuff like that (when they MUST be in a proper
+// UNICODE build). You end up scratching your head and saying, "But that HAS
+// to compile!".
+//
+// So what should you do if you get this error?
+//
+// Make sure that both macros (_UNICODE and UNICODE) are defined before this
+// file is included. You can do that by either
+//
+// a) defining both yourself before any files get included
+// b) including the proper MS headers in the proper order
+// c) including this file before any other file, uncommenting
+// the #defines below, and commenting out the #errors
+//
+// Personally I recommend solution a) but it's your call.
+
+#ifdef _MSC_VER
+ #if defined (_UNICODE) && !defined (UNICODE)
+ #error UNICODE defined but not UNICODE
+ // #define UNICODE // no longer silently fix this
+ #endif
+ #if defined (UNICODE) && !defined (_UNICODE)
+ #error Warning, UNICODE defined but not _UNICODE
+ // #define _UNICODE // no longer silently fix this
+ #endif
+#endif
+
+
+// -----------------------------------------------------------------------------
+// MIN and MAX. The Standard C++ template versions go by so many names (at
+// at least in the MS implementation) that you never know what's available
+// -----------------------------------------------------------------------------
+template<class Type>
+inline const Type& SSMIN(const Type& arg1, const Type& arg2)
+{
+ return arg2 < arg1 ? arg2 : arg1;
+}
+template<class Type>
+inline const Type& SSMAX(const Type& arg1, const Type& arg2)
+{
+ return arg2 > arg1 ? arg2 : arg1;
+}
+
+// If they have not #included W32Base.h (part of my W32 utility library) then
+// we need to define some stuff. Otherwise, this is all defined there.
+
+#if !defined(W32BASE_H)
+
+ // If they want us to use only standard C++ stuff (no Win32 stuff)
+
+ #ifdef SS_ANSI
+
+ // On Win32 we have TCHAR.H so just include it. This is NOT violating
+ // the spirit of SS_ANSI as we are not calling any Win32 functions here.
+
+ #ifdef SS_WIN32
+
+ #include <TCHAR.H>
+ #include <WTYPES.H>
+ #ifndef STRICT
+ #define STRICT
+ #endif
+
+ // ... but on non-Win32 platforms, we must #define the types we need.
+
+ #else
+
+ typedef const char* PCSTR;
+ typedef char* PSTR;
+ typedef const wchar_t* PCWSTR;
+ typedef wchar_t* PWSTR;
+ #ifdef UNICODE
+ typedef wchar_t TCHAR;
+ #else
+ typedef char TCHAR;
+ #endif
+ typedef wchar_t OLECHAR;
+
+ #endif // #ifndef _WIN32
+
+
+ // Make sure ASSERT and verify are defined using only ANSI stuff
+
+ #ifndef ASSERT
+ #include <assert.h>
+ #define ASSERT(f) assert((f))
+ #endif
+ #ifndef VERIFY
+ #ifdef _DEBUG
+ #define VERIFY(x) ASSERT((x))
+ #else
+ #define VERIFY(x) x
+ #endif
+ #endif
+
+ #else // ...else SS_ANSI is NOT defined
+
+ #include <TCHAR.H>
+ #include <WTYPES.H>
+ #ifndef STRICT
+ #define STRICT
+ #endif
+
+ // Make sure ASSERT and verify are defined
+
+ #ifndef ASSERT
+ #include <crtdbg.h>
+ #define ASSERT(f) _ASSERTE((f))
+ #endif
+ #ifndef VERIFY
+ #ifdef _DEBUG
+ #define VERIFY(x) ASSERT((x))
+ #else
+ #define VERIFY(x) x
+ #endif
+ #endif
+
+ #endif // #ifdef SS_ANSI
+
+ #ifndef UNUSED
+ #define UNUSED(x) x
+ #endif
+
+#endif // #ifndef W32BASE_H
+
+// Standard headers needed
+
+#include <string> // basic_string
+#include <algorithm> // for_each, etc.
+#include <functional> // for StdStringLessNoCase, et al
+#ifndef SS_NO_LOCALE
+ #include <locale> // for various facets
+#endif
+
+// If this is a recent enough version of VC include comdef.h, so we can write
+// member functions to deal with COM types & compiler support classes e.g.
+// _bstr_t
+
+#if defined (_MSC_VER) && (_MSC_VER >= 1100)
+ #include <comdef.h>
+ #define SS_INC_COMDEF // signal that we #included MS comdef.h file
+ #define STDSTRING_INC_COMDEF
+ #define SS_NOTHROW __declspec(nothrow)
+#else
+ #define SS_NOTHROW
+#endif
+
+#ifndef TRACE
+ #define TRACE_DEFINED_HERE
+ #define TRACE
+#endif
+
+// Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the
+// versions with the "L" in front of them because that's a leftover from Win 16
+// days, even though it evaluates to the same thing. Therefore, Define a PCSTR
+// as an LPCTSTR.
+
+#if !defined(PCTSTR) && !defined(PCTSTR_DEFINED)
+ typedef const TCHAR* PCTSTR;
+ #define PCTSTR_DEFINED
+#endif
+
+#if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED)
+ typedef const OLECHAR* PCOLESTR;
+ #define PCOLESTR_DEFINED
+#endif
+
+#if !defined(POLESTR) && !defined(POLESTR_DEFINED)
+ typedef OLECHAR* POLESTR;
+ #define POLESTR_DEFINED
+#endif
+
+#if !defined(PCUSTR) && !defined(PCUSTR_DEFINED)
+ typedef const unsigned char* PCUSTR;
+ typedef unsigned char* PUSTR;
+ #define PCUSTR_DEFINED
+#endif
+
+
+// SGI compiler 7.3 doesnt know these types - oh and btw, remember to use
+// -LANG:std in the CXX Flags
+#if defined(__sgi)
+ typedef unsigned long DWORD;
+ typedef void * LPCVOID;
+#endif
+
+
+// SS_USE_FACET macro and why we need it:
+//
+// Since I'm a good little Standard C++ programmer, I use locales. Thus, I
+// need to make use of the use_facet<> template function here. Unfortunately,
+// this need is complicated by the fact the MS' implementation of the Standard
+// C++ Library has a non-standard version of use_facet that takes more
+// arguments than the standard dictates. Since I'm trying to write CStdString
+// to work with any version of the Standard library, this presents a problem.
+//
+// The upshot of this is that I can't do 'use_facet' directly. The MS' docs
+// tell me that I have to use a macro, _USE() instead. Since _USE obviously
+// won't be available in other implementations, this means that I have to write
+// my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the
+// standard, use_facet.
+//
+// If you are having trouble with the SS_USE_FACET macro, in your implementation
+// of the Standard C++ Library, you can define your own version of SS_USE_FACET.
+
+#ifndef schMSG
+ #define schSTR(x) #x
+ #define schSTR2(x) schSTR(x)
+ #define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc)
+#endif
+
+#ifndef SS_USE_FACET
+
+ // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for
+ // all MSVC builds, erroneously in my opinion. It causes problems for
+ // my SS_ANSI builds. In my code, I always comment out that line. You'll
+ // find it in \stlport\config\stl_msvc.h
+
+ #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )
+
+ #if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER)
+ #ifdef SS_ANSI
+ #pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!)
+ #endif
+ #endif
+ #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
+
+ #elif defined(_MSC_VER )
+
+ #define SS_USE_FACET(loc, fac) std::_USE(loc, fac)
+
+ // ...and
+ #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
+
+ #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)
+
+ #else
+
+ #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
+
+ #endif
+
+#endif
+
+// =============================================================================
+// UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones.
+// =============================================================================
+
+#include <wchar.h> // Added to Std Library with Amendment #1.
+
+// First define the conversion helper functions. We define these regardless of
+// any preprocessor macro settings since their names won't collide.
+
+// Not sure if we need all these headers. I believe ANSI says we do.
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <wctype.h>
+#include <ctype.h>
+#include <stdlib.h>
+#ifndef va_start
+ #include <varargs.h>
+#endif
+
+
+#ifdef SS_NO_LOCALE
+
+ #if defined(_WIN32) || defined (_WIN32_WCE)
+
+ inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc,
+ UINT acp=CP_ACP)
+ {
+ ASSERT(0 != pSrcA);
+ ASSERT(0 != pDstW);
+ pDstW[0] = '\0';
+ MultiByteToWideChar(acp, 0, pSrcA, nSrc, pDstW, nDst);
+ return pDstW;
+ }
+ inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc,
+ UINT acp=CP_ACP)
+ {
+ return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp);
+ }
+
+ inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
+ UINT acp=CP_ACP)
+ {
+ ASSERT(0 != pDstA);
+ ASSERT(0 != pSrcW);
+ pDstA[0] = '\0';
+ WideCharToMultiByte(acp, 0, pSrcW, nSrc, pDstA, nDst, 0, 0);
+ return pDstA;
+ }
+ inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
+ UINT acp=CP_ACP)
+ {
+ return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp);
+ }
+ #else
+ #endif
+
+#else
+
+ // StdCodeCvt - made to look like Win32 functions WideCharToMultiByte
+ // and MultiByteToWideChar but uses locales in SS_ANSI
+ // builds. There are a number of overloads.
+ // First argument is the destination buffer.
+ // Second argument is the source buffer
+ //#if defined (SS_ANSI) || !defined (SS_WIN32)
+
+ // 'SSCodeCvt' - shorthand name for the codecvt facet we use
+
+ typedef std::codecvt<wchar_t, char, mbstate_t> SSCodeCvt;
+
+ inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc,
+ const std::locale& loc=std::locale())
+ {
+ ASSERT(0 != pSrcA);
+ ASSERT(0 != pDstW);
+
+ pDstW[0] = '\0';
+
+ if ( nSrc > 0 )
+ {
+ PCSTR pNextSrcA = pSrcA;
+ PWSTR pNextDstW = pDstW;
+ SSCodeCvt::result res = SSCodeCvt::ok;
+ const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);
+ SSCodeCvt::state_type st= { 0 };
+ res = conv.in(st,
+ pSrcA, pSrcA + nSrc, pNextSrcA,
+ pDstW, pDstW + nDst, pNextDstW);
+#ifdef _LINUX
+#define ASSERT2(a) if (!(a)) {fprintf(stderr, "StdString: Assertion Failed on line %d\n", __LINE__);}
+#else
+#define ASSERT2 ASSERT
+#endif
+ ASSERT2(SSCodeCvt::ok == res);
+ ASSERT2(SSCodeCvt::error != res);
+ ASSERT2(pNextDstW >= pDstW);
+ ASSERT2(pNextSrcA >= pSrcA);
+#undef ASSERT2
+ // Null terminate the converted string
+
+ if ( pNextDstW - pDstW > nDst )
+ *(pDstW + nDst) = '\0';
+ else
+ *pNextDstW = '\0';
+ }
+ return pDstW;
+ }
+ inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc,
+ const std::locale& loc=std::locale())
+ {
+ return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, loc);
+ }
+
+ inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
+ const std::locale& loc=std::locale())
+ {
+ ASSERT(0 != pDstA);
+ ASSERT(0 != pSrcW);
+
+ pDstA[0] = '\0';
+
+ if ( nSrc > 0 )
+ {
+ PSTR pNextDstA = pDstA;
+ PCWSTR pNextSrcW = pSrcW;
+ SSCodeCvt::result res = SSCodeCvt::ok;
+ const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);
+ SSCodeCvt::state_type st= { 0 };
+ res = conv.out(st,
+ pSrcW, pSrcW + nSrc, pNextSrcW,
+ pDstA, pDstA + nDst, pNextDstA);
+#ifdef _LINUX
+#define ASSERT2(a) if (!(a)) {fprintf(stderr, "StdString: Assertion Failed on line %d\n", __LINE__);}
+#else
+#define ASSERT2 ASSERT
+#endif
+ ASSERT2(SSCodeCvt::error != res);
+ ASSERT2(SSCodeCvt::ok == res); // strict, comment out for sanity
+ ASSERT2(pNextDstA >= pDstA);
+ ASSERT2(pNextSrcW >= pSrcW);
+#undef ASSERT2
+
+ // Null terminate the converted string
+
+ if ( pNextDstA - pDstA > nDst )
+ *(pDstA + nDst) = '\0';
+ else
+ *pNextDstA = '\0';
+ }
+ return pDstA;
+ }
+
+ inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
+ const std::locale& loc=std::locale())
+ {
+ return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, loc);
+ }
+
+#endif
+
+
+
+// Unicode/MBCS conversion macros are only available on implementations of
+// the "C" library that have the non-standard _alloca function. As far as I
+// know that's only Microsoft's though I've heard that the function exists
+// elsewhere.
+
+#if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION
+
+ #include <malloc.h> // needed for _alloca
+
+ // Define our conversion macros to look exactly like Microsoft's to
+ // facilitate using this stuff both with and without MFC/ATL
+
+ #ifdef _CONVERSION_USES_THREAD_LOCALE
+
+ #ifndef _DEBUG
+ #define SSCVT int _cvt; _cvt; UINT _acp=GetACP(); \
+ _acp; PCWSTR _pw; _pw; PCSTR _pa; _pa
+ #else
+ #define SSCVT int _cvt = 0; _cvt; UINT _acp=GetACP();\
+ _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa
+ #endif
+ #define SSA2W(pa) (\
+ ((_pa = pa) == 0) ? 0 : (\
+ _cvt = (sslen(_pa)),\
+ StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
+ _pa, _cvt, _acp)))
+ #define SSW2A(pw) (\
+ ((_pw = pw) == 0) ? 0 : (\
+ _cvt = sslen(_pw), \
+ StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
+ _pw, _cvt, _acp)))
+ #else
+
+ #ifndef _DEBUG
+ #define SSCVT int _cvt; _cvt; UINT _acp=CP_ACP; _acp;\
+ PCWSTR _pw; _pw; PCSTR _pa; _pa
+ #else
+ #define SSCVT int _cvt = 0; _cvt; UINT _acp=CP_ACP; \
+ _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa
+ #endif
+ #define SSA2W(pa) (\
+ ((_pa = pa) == 0) ? 0 : (\
+ _cvt = (sslen(_pa)),\
+ StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
+ _pa, _cvt)))
+ #define SSW2A(pw) (\
+ ((_pw = pw) == 0) ? 0 : (\
+ _cvt = (sslen(_pw)),\
+ StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
+ _pw, _cvt)))
+ #endif
+
+ #define SSA2CW(pa) ((PCWSTR)SSA2W((pa)))
+ #define SSW2CA(pw) ((PCSTR)SSW2A((pw)))
+
+ #ifdef UNICODE
+ #define SST2A SSW2A
+ #define SSA2T SSA2W
+ #define SST2CA SSW2CA
+ #define SSA2CT SSA2CW
+ // (Did you get a compiler error here about not being able to convert
+ // PTSTR into PWSTR? Then your _UNICODE and UNICODE flags are messed
+ // up. Best bet: #define BOTH macros before including any MS headers.)
+ inline PWSTR SST2W(PTSTR p) { return p; }
+ inline PTSTR SSW2T(PWSTR p) { return p; }
+ inline PCWSTR SST2CW(PCTSTR p) { return p; }
+ inline PCTSTR SSW2CT(PCWSTR p) { return p; }
+ #else
+ #define SST2W SSA2W
+ #define SSW2T SSW2A
+ #define SST2CW SSA2CW
+ #define SSW2CT SSW2CA
+ inline PSTR SST2A(PTSTR p) { return p; }
+ inline PTSTR SSA2T(PSTR p) { return p; }
+ inline PCSTR SST2CA(PCTSTR p) { return p; }
+ inline PCTSTR SSA2CT(PCSTR p) { return p; }
+ #endif // #ifdef UNICODE
+
+ #if defined(UNICODE)
+ // in these cases the default (TCHAR) is the same as OLECHAR
+ inline PCOLESTR SST2COLE(PCTSTR p) { return p; }
+ inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; }
+ inline POLESTR SST2OLE(PTSTR p) { return p; }
+ inline PTSTR SSOLE2T(POLESTR p) { return p; }
+ #elif defined(OLE2ANSI)
+ // in these cases the default (TCHAR) is the same as OLECHAR
+ inline PCOLESTR SST2COLE(PCTSTR p) { return p; }
+ inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; }
+ inline POLESTR SST2OLE(PTSTR p) { return p; }
+ inline PTSTR SSOLE2T(POLESTR p) { return p; }
+ #else
+ //CharNextW doesn't work on Win95 so we use this
+ #define SST2COLE(pa) SSA2CW((pa))
+ #define SST2OLE(pa) SSA2W((pa))
+ #define SSOLE2CT(po) SSW2CA((po))
+ #define SSOLE2T(po) SSW2A((po))
+ #endif
+
+ #ifdef OLE2ANSI
+ #define SSW2OLE SSW2A
+ #define SSOLE2W SSA2W
+ #define SSW2COLE SSW2CA
+ #define SSOLE2CW SSA2CW
+ inline POLESTR SSA2OLE(PSTR p) { return p; }
+ inline PSTR SSOLE2A(POLESTR p) { return p; }
+ inline PCOLESTR SSA2COLE(PCSTR p) { return p; }
+ inline PCSTR SSOLE2CA(PCOLESTR p){ return p; }
+ #else
+ #define SSA2OLE SSA2W
+ #define SSOLE2A SSW2A
+ #define SSA2COLE SSA2CW
+ #define SSOLE2CA SSW2CA
+ inline POLESTR SSW2OLE(PWSTR p) { return p; }
+ inline PWSTR SSOLE2W(POLESTR p) { return p; }
+ inline PCOLESTR SSW2COLE(PCWSTR p) { return p; }
+ inline PCWSTR SSOLE2CW(PCOLESTR p){ return p; }
+ #endif
+
+ // Above we've defined macros that look like MS' but all have
+ // an 'SS' prefix. Now we need the real macros. We'll either
+ // get them from the macros above or from MFC/ATL.
+
+ #if defined (USES_CONVERSION)
+
+ #define _NO_STDCONVERSION // just to be consistent
+
+ #else
+
+ #ifdef _MFC_VER
+
+ #include <afxconv.h>
+ #define _NO_STDCONVERSION // just to be consistent
+
+ #else
+
+ #define USES_CONVERSION SSCVT
+ #define A2CW SSA2CW
+ #define W2CA SSW2CA
+ #define T2A SST2A
+ #define A2T SSA2T
+ #define T2W SST2W
+ #define W2T SSW2T
+ #define T2CA SST2CA
+ #define A2CT SSA2CT
+ #define T2CW SST2CW
+ #define W2CT SSW2CT
+ #define ocslen sslen
+ #define ocscpy sscpy
+ #define T2COLE SST2COLE
+ #define OLE2CT SSOLE2CT
+ #define T2OLE SST2COLE
+ #define OLE2T SSOLE2CT
+ #define A2OLE SSA2OLE
+ #define OLE2A SSOLE2A
+ #define W2OLE SSW2OLE
+ #define OLE2W SSOLE2W
+ #define A2COLE SSA2COLE
+ #define OLE2CA SSOLE2CA
+ #define W2COLE SSW2COLE
+ #define OLE2CW SSOLE2CW
+
+ #endif // #ifdef _MFC_VER
+ #endif // #ifndef USES_CONVERSION
+#endif // #ifndef SS_NO_CONVERSION
+
+// Define ostring - generic name for std::basic_string<OLECHAR>
+
+#if !defined(ostring) && !defined(OSTRING_DEFINED)
+ typedef std::basic_string<OLECHAR> ostring;
+ #define OSTRING_DEFINED
+#endif
+
+// StdCodeCvt when there's no conversion to be done
+template <typename T>
+inline T* StdCodeCvt(T* pDst, int nDst, const T* pSrc, int nSrc)
+{
+ int nChars = SSMIN(nSrc, nDst);
+
+ if ( nChars > 0 )
+ {
+ pDst[0] = '\0';
+ std::basic_string<T>::traits_type::copy(pDst, pSrc, nChars);
+// std::char_traits<T>::copy(pDst, pSrc, nChars);
+ pDst[nChars] = '\0';
+ }
+
+ return pDst;
+}
+inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCUSTR pSrc, int nSrc)
+{
+ return StdCodeCvt(pDst, nDst, (PCSTR)pSrc, nSrc);
+}
+inline PUSTR StdCodeCvt(PUSTR pDst, int nDst, PCSTR pSrc, int nSrc)
+{
+ return (PUSTR)StdCodeCvt((PSTR)pDst, nDst, pSrc, nSrc);
+}
+
+// Define tstring -- generic name for std::basic_string<TCHAR>
+
+#if !defined(tstring) && !defined(TSTRING_DEFINED)
+ typedef std::basic_string<TCHAR> tstring;
+ #define TSTRING_DEFINED
+#endif
+
+// a very shorthand way of applying the fix for KB problem Q172398
+// (basic_string assignment bug)
+
+#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
+ #define Q172398(x) (x).erase()
+#else
+ #define Q172398(x)
+#endif
+
+// =============================================================================
+// INLINE FUNCTIONS ON WHICH CSTDSTRING RELIES
+//
+// Usually for generic text mapping, we rely on preprocessor macro definitions
+// to map to string functions. However the CStdStr<> template cannot use
+// macro-based generic text mappings because its character types do not get
+// resolved until template processing which comes AFTER macro processing. In
+// other words, the preprocessor macro UNICODE is of little help to us in the
+// CStdStr template
+//
+// Therefore, to keep the CStdStr declaration simple, we have these inline
+// functions. The template calls them often. Since they are inline (and NOT
+// exported when this is built as a DLL), they will probably be resolved away
+// to nothing.
+//
+// Without these functions, the CStdStr<> template would probably have to broken
+// out into two, almost identical classes. Either that or it would be a huge,
+// convoluted mess, with tons of "if" statements all over the place checking the
+// size of template parameter CT.
+// =============================================================================
+
+#ifdef SS_NO_LOCALE
+
+ // --------------------------------------------------------------------------
+ // Win32 GetStringTypeEx wrappers
+ // --------------------------------------------------------------------------
+ inline bool wsGetStringType(LCID lc, DWORD dwT, PCSTR pS, int nSize,
+ WORD* pWd)
+ {
+ return FALSE != GetStringTypeExA(lc, dwT, pS, nSize, pWd);
+ }
+ inline bool wsGetStringType(LCID lc, DWORD dwT, PCWSTR pS, int nSize,
+ WORD* pWd)
+ {
+ return FALSE != GetStringTypeExW(lc, dwT, pS, nSize, pWd);
+ }
+
+
+ template<typename CT>
+ inline bool ssisspace (CT t)
+ {
+ WORD toYourMother;
+ return wsGetStringType(GetThreadLocale(), CT_CTYPE1, &t, 1, &toYourMother)
+ && 0 != (C1_BLANK & toYourMother);
+ }
+
+#endif
+
+// If they defined SS_NO_REFCOUNT, then we must convert all assignments
+
+#if defined (_MSC_VER) && (_MSC_VER < 1300)
+ #ifdef SS_NO_REFCOUNT
+ #define SSREF(x) (x).c_str()
+ #else
+ #define SSREF(x) (x)
+ #endif
+#else
+ #define SSREF(x) (x)
+#endif
+
+// -----------------------------------------------------------------------------
+// sslen: strlen/wcslen wrappers
+// -----------------------------------------------------------------------------
+template<typename CT> inline int sslen(const CT* pT)
+{
+ return 0 == pT ? 0 : (int)std::basic_string<CT>::traits_type::length(pT);
+// return 0 == pT ? 0 : std::char_traits<CT>::length(pT);
+}
+inline SS_NOTHROW int sslen(const std::string& s)
+{
+ return static_cast<int>(s.length());
+}
+inline SS_NOTHROW int sslen(const std::wstring& s)
+{
+ return static_cast<int>(s.length());
+}
+
+// -----------------------------------------------------------------------------
+// sstolower/sstoupper -- convert characters to upper/lower case
+// -----------------------------------------------------------------------------
+
+#ifdef SS_NO_LOCALE
+ inline char sstoupper(char ch) { return (char)::toupper(ch); }
+ inline wchar_t sstoupper(wchar_t ch){ return (wchar_t)::towupper(ch); }
+ inline char sstolower(char ch) { return (char)::tolower(ch); }
+ inline wchar_t sstolower(wchar_t ch){ return (wchar_t)::tolower(ch); }
+#else
+ template<typename CT>
+ inline CT sstolower(const CT& t, const std::locale& loc = std::locale())
+ {
+ return std::tolower<CT>(t, loc);
+ }
+ template<typename CT>
+ inline CT sstoupper(const CT& t, const std::locale& loc = std::locale())
+ {
+ return std::toupper<CT>(t, loc);
+ }
+#endif
+
+// -----------------------------------------------------------------------------
+// ssasn: assignment functions -- assign "sSrc" to "sDst"
+// -----------------------------------------------------------------------------
+typedef std::string::size_type SS_SIZETYPE; // just for shorthand, really
+typedef std::string::pointer SS_PTRTYPE;
+typedef std::wstring::size_type SW_SIZETYPE;
+typedef std::wstring::pointer SW_PTRTYPE;
+
+
+template <typename T>
+inline void ssasn(std::basic_string<T>& sDst, const std::basic_string<T>& sSrc)
+{
+ if ( sDst.c_str() != sSrc.c_str() )
+ {
+ sDst.erase();
+ sDst.assign(SSREF(sSrc));
+ }
+}
+template <typename T>
+inline void ssasn(std::basic_string<T>& sDst, const T *pA)
+{
+ // Watch out for NULLs, as always.
+
+ if ( 0 == pA )
+ {
+ sDst.erase();
+ }
+
+ // If pA actually points to part of sDst, we must NOT erase(), but
+ // rather take a substring
+
+ else if ( pA >= sDst.c_str() && pA <= sDst.c_str() + sDst.size() )
+ {
+ sDst =sDst.substr(static_cast<typename std::basic_string<T>::size_type>(pA-sDst.c_str()));
+ }
+
+ // Otherwise (most cases) apply the assignment bug fix, if applicable
+ // and do the assignment
+
+ else
+ {
+ Q172398(sDst);
+ sDst.assign(pA);
+ }
+}
+inline void ssasn(std::string& sDst, const std::wstring& sSrc)
+{
+ if ( sSrc.empty() )
+ {
+ sDst.erase();
+ }
+ else
+ {
+ int nDst = static_cast<int>(sSrc.size());
+
+ // In MBCS builds, pad the buffer to account for the possibility of
+ // some 3 byte characters. Not perfect but should get most cases.
+
+#ifdef SS_MBCS
+ // In MBCS builds, we don't know how long the destination string will be.
+ nDst = static_cast<int>(static_cast<double>(nDst) * 1.3);
+ sDst.resize(nDst+1);
+ PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
+ sSrc.c_str(), static_cast<int>(sSrc.size()));
+ sDst.resize(sslen(szCvt));
+#else
+ sDst.resize(nDst+1);
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
+ sSrc.c_str(), static_cast<int>(sSrc.size()));
+ sDst.resize(sSrc.size());
+#endif
+ }
+}
+inline void ssasn(std::string& sDst, PCWSTR pW)
+{
+ int nSrc = sslen(pW);
+ if ( nSrc > 0 )
+ {
+ int nSrc = sslen(pW);
+ int nDst = nSrc;
+
+ // In MBCS builds, pad the buffer to account for the possibility of
+ // some 3 byte characters. Not perfect but should get most cases.
+
+#ifdef SS_MBCS
+ nDst = static_cast<int>(static_cast<double>(nDst) * 1.3);
+ // In MBCS builds, we don't know how long the destination string will be.
+ sDst.resize(nDst + 1);
+ PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
+ pW, nSrc);
+ sDst.resize(sslen(szCvt));
+#else
+ sDst.resize(nDst + 1);
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst, pW, nSrc);
+ sDst.resize(nDst);
+#endif
+ }
+ else
+ {
+ sDst.erase();
+ }
+}
+inline void ssasn(std::string& sDst, const int nNull)
+{
+ //UNUSED(nNull);
+ ASSERT(nNull==0);
+ sDst.assign("");
+}
+#undef StrSizeType
+inline void ssasn(std::wstring& sDst, const std::string& sSrc)
+{
+ if ( sSrc.empty() )
+ {
+ sDst.erase();
+ }
+ else
+ {
+ int nSrc = static_cast<int>(sSrc.size());
+ int nDst = nSrc;
+
+ sDst.resize(nSrc+1);
+ PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), nDst,
+ sSrc.c_str(), nSrc);
+
+ sDst.resize(sslen(szCvt));
+ }
+}
+inline void ssasn(std::wstring& sDst, PCSTR pA)
+{
+ int nSrc = sslen(pA);
+
+ if ( 0 == nSrc )
+ {
+ sDst.erase();
+ }
+ else
+ {
+ int nDst = nSrc;
+ sDst.resize(nDst+1);
+ PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), nDst, pA,
+ nSrc);
+
+ sDst.resize(sslen(szCvt));
+ }
+}
+inline void ssasn(std::wstring& sDst, const int nNull)
+{
+ //UNUSED(nNull);
+ ASSERT(nNull==0);
+ sDst.assign(L"");
+}
+
+// -----------------------------------------------------------------------------
+// ssadd: string object concatenation -- add second argument to first
+// -----------------------------------------------------------------------------
+inline void ssadd(std::string& sDst, const std::wstring& sSrc)
+{
+ int nSrc = static_cast<int>(sSrc.size());
+
+ if ( nSrc > 0 )
+ {
+ int nDst = static_cast<int>(sDst.size());
+ int nAdd = nSrc;
+
+ // In MBCS builds, pad the buffer to account for the possibility of
+ // some 3 byte characters. Not perfect but should get most cases.
+
+#ifdef SS_MBCS
+ nAdd = static_cast<int>(static_cast<double>(nAdd) * 1.3);
+ sDst.resize(nDst+nAdd+1);
+ PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst),
+ nAdd, sSrc.c_str(), nSrc);
+ sDst.resize(nDst + sslen(szCvt));
+#else
+ sDst.resize(nDst+nAdd+1);
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst), nAdd, sSrc.c_str(), nSrc);
+ sDst.resize(nDst + nAdd);
+#endif
+ }
+}
+template <typename T>
+inline void ssadd(typename std::basic_string<T>& sDst, const typename std::basic_string<T>& sSrc)
+{
+ sDst += sSrc;
+}
+inline void ssadd(std::string& sDst, PCWSTR pW)
+{
+ int nSrc = sslen(pW);
+ if ( nSrc > 0 )
+ {
+ int nDst = static_cast<int>(sDst.size());
+ int nAdd = nSrc;
+
+#ifdef SS_MBCS
+ nAdd = static_cast<int>(static_cast<double>(nAdd) * 1.3);
+ sDst.resize(nDst + nAdd + 1);
+ PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst),
+ nAdd, pW, nSrc);
+ sDst.resize(nDst + sslen(szCvt));
+#else
+ sDst.resize(nDst + nAdd + 1);
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst), nAdd, pW, nSrc);
+ sDst.resize(nDst + nSrc);
+#endif
+ }
+}
+template <typename T>
+inline void ssadd(typename std::basic_string<T>& sDst, const T *pA)
+{
+ if ( pA )
+ {
+ // If the string being added is our internal string or a part of our
+ // internal string, then we must NOT do any reallocation without
+ // first copying that string to another object (since we're using a
+ // direct pointer)
+
+ if ( pA >= sDst.c_str() && pA <= sDst.c_str()+sDst.length())
+ {
+ if ( sDst.capacity() <= sDst.size()+sslen(pA) )
+ sDst.append(std::basic_string<T>(pA));
+ else
+ sDst.append(pA);
+ }
+ else
+ {
+ sDst.append(pA);
+ }
+ }
+}
+inline void ssadd(std::wstring& sDst, const std::string& sSrc)
+{
+ if ( !sSrc.empty() )
+ {
+ int nSrc = static_cast<int>(sSrc.size());
+ int nDst = static_cast<int>(sDst.size());
+
+ sDst.resize(nDst + nSrc + 1);
+#ifdef SS_MBCS
+ PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst),
+ nSrc, sSrc.c_str(), nSrc+1);
+ sDst.resize(nDst + sslen(szCvt));
+#else
+ StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst), nSrc, sSrc.c_str(), nSrc+1);
+ sDst.resize(nDst + nSrc);
+#endif
+ }
+}
+inline void ssadd(std::wstring& sDst, PCSTR pA)
+{
+ int nSrc = sslen(pA);
+
+ if ( nSrc > 0 )
+ {
+ int nDst = static_cast<int>(sDst.size());
+
+ sDst.resize(nDst + nSrc + 1);
+#ifdef SS_MBCS
+ PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst),
+ nSrc, pA, nSrc+1);
+ sDst.resize(nDst + sslen(szCvt));
+#else
+ StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst), nSrc, pA, nSrc+1);
+ sDst.resize(nDst + nSrc);
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------------
+// sscmp: comparison (case sensitive, not affected by locale)
+// -----------------------------------------------------------------------------
+template<typename CT>
+inline int sscmp(const CT* pA1, const CT* pA2)
+{
+ CT f;
+ CT l;
+
+ do
+ {
+ f = *(pA1++);
+ l = *(pA2++);
+ } while ( (f) && (f == l) );
+
+ return (int)(f - l);
+}
+
+// -----------------------------------------------------------------------------
+// ssicmp: comparison (case INsensitive, not affected by locale)
+// -----------------------------------------------------------------------------
+template<typename CT>
+inline int ssicmp(const CT* pA1, const CT* pA2)
+{
+ // Using the "C" locale = "not affected by locale"
+
+ std::locale loc = std::locale::classic();
+ const std::ctype<CT>& ct = SS_USE_FACET(loc, std::ctype<CT>);
+ CT f;
+ CT l;
+
+ do
+ {
+ f = ct.tolower(*(pA1++));
+ l = ct.tolower(*(pA2++));
+ } while ( (f) && (f == l) );
+
+ return (int)(f - l);
+}
+
+// -----------------------------------------------------------------------------
+// ssupr/sslwr: Uppercase/Lowercase conversion functions
+// -----------------------------------------------------------------------------
+
+template<typename CT>
+inline void sslwr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
+{
+ SS_USE_FACET(loc, std::ctype<CT>).tolower(pT, pT+nLen);
+}
+template<typename CT>
+inline void ssupr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
+{
+ SS_USE_FACET(loc, std::ctype<CT>).toupper(pT, pT+nLen);
+}
+
+// -----------------------------------------------------------------------------
+// vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents. In standard
+// builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.
+//
+// -----------------------------------------------------------------------------
+// Borland's headers put some ANSI "C" functions in the 'std' namespace.
+// Promote them to the global namespace so we can use them here.
+
+#if defined(__BORLANDC__)
+ using std::vsprintf;
+ using std::vswprintf;
+#endif
+
+ // GNU is supposed to have vsnprintf and vsnwprintf. But only the newer
+ // distributions do.
+
+#if defined(__GNUC__)
+
+ inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
+ {
+ return vsnprintf(pA, nCount, pFmtA, vl);
+ }
+ inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
+ {
+ return vswprintf(pW, nCount, pFmtW, vl);
+ }
+
+ // Microsofties can use
+#elif defined(_MSC_VER) && !defined(SS_ANSI)
+
+ inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
+ {
+ return _vsnprintf(pA, nCount, pFmtA, vl);
+ }
+ inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
+ {
+ return _vsnwprintf(pW, nCount, pFmtW, vl);
+ }
+
+#elif defined (SS_DANGEROUS_FORMAT) // ignore buffer size parameter if needed?
+
+ inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl)
+ {
+ return vsprintf(pA, pFmtA, vl);
+ }
+
+ inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
+ {
+ // JMO: Some distributions of the "C" have a version of vswprintf that
+ // takes 3 arguments (e.g. Microsoft, Borland, GNU). Others have a
+ // version which takes 4 arguments (an extra "count" argument in the
+ // second position. The best stab I can take at this so far is that if
+ // you are NOT running with MS, Borland, or GNU, then I'll assume you
+ // have the version that takes 4 arguments.
+ //
+ // I'm sure that these checks don't catch every platform correctly so if
+ // you get compiler errors on one of the lines immediately below, it's
+ // probably because your implemntation takes a different number of
+ // arguments. You can comment out the offending line (and use the
+ // alternate version) or you can figure out what compiler flag to check
+ // and add that preprocessor check in. Regardless, if you get an error
+ // on these lines, I'd sure like to hear from you about it.
+ //
+ // Thanks to Ronny Schulz for the SGI-specific checks here.
+
+// #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)
+ #if !defined(_MSC_VER) \
+ && !defined (__BORLANDC__) \
+ && !defined(__GNUC__) \
+ && !defined(__sgi)
+
+ return vswprintf(pW, nCount, pFmtW, vl);
+
+ // suddenly with the current SGI 7.3 compiler there is no such function as
+ // vswprintf and the substitute needs explicit casts to compile
+
+ #elif defined(__sgi)
+
+ nCount;
+ return vsprintf( (char *)pW, (char *)pFmtW, vl);
+
+ #else
+
+ nCount;
+ return vswprintf(pW, pFmtW, vl);
+
+ #endif
+
+ }
+
+#endif
+
+ // GOT COMPILER PROBLEMS HERE?
+ // ---------------------------
+ // Does your compiler choke on one or more of the following 2 functions? It
+ // probably means that you don't have have either vsnprintf or vsnwprintf in
+ // your version of the CRT. This is understandable since neither is an ANSI
+ // "C" function. However it still leaves you in a dilemma. In order to make
+ // this code build, you're going to have to to use some non-length-checked
+ // formatting functions that every CRT has: vsprintf and vswprintf.
+ //
+ // This is very dangerous. With the proper erroneous (or malicious) code, it
+ // can lead to buffer overlows and crashing your PC. Use at your own risk
+ // In order to use them, just #define SS_DANGEROUS_FORMAT at the top of
+ // this file.
+ //
+ // Even THEN you might not be all the way home due to some non-conforming
+ // distributions. More on this in the comments below.
+
+ inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
+ {
+ #ifdef _MSC_VER
+ return _vsnprintf(pA, nCount, pFmtA, vl);
+ #else
+ return vsnprintf(pA, nCount, pFmtA, vl);
+ #endif
+ }
+ inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
+ {
+ #ifdef _MSC_VER
+ return _vsnwprintf(pW, nCount, pFmtW, vl);
+ #else
+ return vswprintf(pW, nCount, pFmtW, vl);
+ #endif
+ }
+
+
+
+
+// -----------------------------------------------------------------------------
+// ssload: Type safe, overloaded ::LoadString wrappers
+// There is no equivalent of these in non-Win32-specific builds. However, I'm
+// thinking that with the message facet, there might eventually be one
+// -----------------------------------------------------------------------------
+#if defined (SS_WIN32) && !defined(SS_ANSI)
+ inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax)
+ {
+ return ::LoadStringA(hInst, uId, pBuf, nMax);
+ }
+ inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax)
+ {
+ return ::LoadStringW(hInst, uId, pBuf, nMax);
+ }
+#if defined ( _MSC_VER ) && ( _MSC_VER >= 1500 )
+ inline int ssload(HMODULE hInst, UINT uId, uint16_t *pBuf, int nMax)
+ {
+ return 0;
+ }
+ inline int ssload(HMODULE hInst, UINT uId, uint32_t *pBuf, int nMax)
+ {
+ return 0;
+ }
+#endif
+#endif
+
+
+// -----------------------------------------------------------------------------
+// sscoll/ssicoll: Collation wrappers
+// Note -- with MSVC I have reversed the arguments order here because the
+// functions appear to return the opposite of what they should
+// -----------------------------------------------------------------------------
+#ifndef SS_NO_LOCALE
+template <typename CT>
+inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
+{
+ const std::collate<CT>& coll =
+ SS_USE_FACET(std::locale(), std::collate<CT>);
+
+ return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1);
+}
+template <typename CT>
+inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
+{
+ const std::locale loc;
+ const std::collate<CT>& coll = SS_USE_FACET(loc, std::collate<CT>);
+
+ // Some implementations seem to have trouble using the collate<>
+ // facet typedefs so we'll just default to basic_string and hope
+ // that's what the collate facet uses (which it generally should)
+
+// std::collate<CT>::string_type s1(sz1);
+// std::collate<CT>::string_type s2(sz2);
+ const std::basic_string<CT> sEmpty;
+ std::basic_string<CT> s1(sz1 ? sz1 : sEmpty.c_str());
+ std::basic_string<CT> s2(sz2 ? sz2 : sEmpty.c_str());
+
+ sslwr(const_cast<CT*>(s1.c_str()), nLen1, loc);
+ sslwr(const_cast<CT*>(s2.c_str()), nLen2, loc);
+ return coll.compare(s2.c_str(), s2.c_str()+nLen2,
+ s1.c_str(), s1.c_str()+nLen1);
+}
+#endif
+
+
+// -----------------------------------------------------------------------------
+// ssfmtmsg: FormatMessage equivalents. Needed because I added a CString facade
+// Again -- no equivalent of these on non-Win32 builds but their might one day
+// be one if the message facet gets implemented
+// -----------------------------------------------------------------------------
+#if defined (SS_WIN32) && !defined(SS_ANSI)
+ inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
+ DWORD dwLangId, PSTR pBuf, DWORD nSize,
+ va_list* vlArgs)
+ {
+ return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId,
+ pBuf, nSize,vlArgs);
+ }
+ inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
+ DWORD dwLangId, PWSTR pBuf, DWORD nSize,
+ va_list* vlArgs)
+ {
+ return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId,
+ pBuf, nSize,vlArgs);
+ }
+#else
+#endif
+
+
+
+// FUNCTION: sscpy. Copies up to 'nMax' characters from pSrc to pDst.
+// -----------------------------------------------------------------------------
+// FUNCTION: sscpy
+// inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1);
+// inline int sscpy(PUSTR pDst, PCSTR pSrc, int nMax=-1)
+// inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1);
+// inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1);
+// inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1);
+//
+// DESCRIPTION:
+// This function is very much (but not exactly) like strcpy. These
+// overloads simplify copying one C-style string into another by allowing
+// the caller to specify two different types of strings if necessary.
+//
+// The strings must NOT overlap
+//
+// "Character" is expressed in terms of the destination string, not
+// the source. If no 'nMax' argument is supplied, then the number of
+// characters copied will be sslen(pSrc). A NULL terminator will
+// also be added so pDst must actually be big enough to hold nMax+1
+// characters. The return value is the number of characters copied,
+// not including the NULL terminator.
+//
+// PARAMETERS:
+// pSrc - the string to be copied FROM. May be a char based string, an
+// MBCS string (in Win32 builds) or a wide string (wchar_t).
+// pSrc - the string to be copied TO. Also may be either MBCS or wide
+// nMax - the maximum number of characters to be copied into szDest. Note
+// that this is expressed in whatever a "character" means to pDst.
+// If pDst is a wchar_t type string than this will be the maximum
+// number of wchar_ts that my be copied. The pDst string must be
+// large enough to hold least nMaxChars+1 characters.
+// If the caller supplies no argument for nMax this is a signal to
+// the routine to copy all the characters in pSrc, regardless of
+// how long it is.
+//
+// RETURN VALUE: none
+// -----------------------------------------------------------------------------
+
+template<typename CT1, typename CT2>
+inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nMax)
+{
+ // Note -- we assume pDst is big enough to hold pSrc. If not, we're in
+ // big trouble. No bounds checking. Caveat emptor.
+
+ int nSrc = sslen(pSrc);
+
+ const CT1* szCvt = StdCodeCvt(pDst, nMax, pSrc, nSrc);
+
+ // If we're copying the same size characters, then all the "code convert"
+ // just did was basically memcpy so the #of characters copied is the same
+ // as the number requested. I should probably specialize this function
+ // template to achieve this purpose as it is silly to do a runtime check
+ // of a fact known at compile time. I'll get around to it.
+
+ return sslen(szCvt);
+}
+
+template<typename T>
+inline int sscpycvt(T* pDst, const T* pSrc, int nMax)
+{
+ int nCount = nMax;
+ for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount)
+ std::basic_string<T>::traits_type::assign(*pDst, *pSrc);
+
+ *pDst = 0;
+ return nMax - nCount;
+}
+
+inline int sscpycvt(PWSTR pDst, PCSTR pSrc, int nMax)
+{
+ // Note -- we assume pDst is big enough to hold pSrc. If not, we're in
+ // big trouble. No bounds checking. Caveat emptor.
+
+ const PWSTR szCvt = StdCodeCvt(pDst, nMax, pSrc, nMax);
+ return sslen(szCvt);
+}
+
+template<typename CT1, typename CT2>
+inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen)
+{
+ return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));
+}
+template<typename CT1, typename CT2>
+inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax)
+{
+ return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));
+}
+template<typename CT1, typename CT2>
+inline int sscpy(CT1* pDst, const CT2* pSrc)
+{
+ return sscpycvt(pDst, pSrc, sslen(pSrc));
+}
+template<typename CT1, typename CT2>
+inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc, int nMax)
+{
+ return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length()));
+}
+template<typename CT1, typename CT2>
+inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc)
+{
+ return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length());
+}
+
+#ifdef SS_INC_COMDEF
+ template<typename CT1>
+ inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax)
+ {
+ return sscpycvt(pDst, static_cast<PCOLESTR>(bs),
+ SSMIN(nMax, static_cast<int>(bs.length())));
+ }
+ template<typename CT1>
+ inline int sscpy(CT1* pDst, const _bstr_t& bs)
+ {
+ return sscpy(pDst, bs, static_cast<int>(bs.length()));
+ }
+#endif
+
+
+// -----------------------------------------------------------------------------
+// Functional objects for changing case. They also let you pass locales
+// -----------------------------------------------------------------------------
+
+#ifdef SS_NO_LOCALE
+ template<typename CT>
+ struct SSToUpper : public std::unary_function<CT, CT>
+ {
+ inline CT operator()(const CT& t) const
+ {
+ return sstoupper(t);
+ }
+ };
+ template<typename CT>
+ struct SSToLower : public std::unary_function<CT, CT>
+ {
+ inline CT operator()(const CT& t) const
+ {
+ return sstolower(t);
+ }
+ };
+#else
+ template<typename CT>
+ struct SSToUpper : public std::binary_function<CT, std::locale, CT>
+ {
+ inline CT operator()(const CT& t, const std::locale& loc) const
+ {
+ return sstoupper<CT>(t, loc);
+ }
+ };
+ template<typename CT>
+ struct SSToLower : public std::binary_function<CT, std::locale, CT>
+ {
+ inline CT operator()(const CT& t, const std::locale& loc) const
+ {
+ return sstolower<CT>(t, loc);
+ }
+ };
+#endif
+
+// This struct is used for TrimRight() and TrimLeft() function implementations.
+//template<typename CT>
+//struct NotSpace : public std::unary_function<CT, bool>
+//{
+// const std::locale& loc;
+// inline NotSpace(const std::locale& locArg) : loc(locArg) {}
+// inline bool operator() (CT t) { return !std::isspace(t, loc); }
+//};
+template<typename CT>
+struct NotSpace : public std::unary_function<CT, bool>
+{
+ // DINKUMWARE BUG:
+ // Note -- using std::isspace in a COM DLL gives us access violations
+ // because it causes the dynamic addition of a function to be called
+ // when the library shuts down. Unfortunately the list is maintained
+ // in DLL memory but the function is in static memory. So the COM DLL
+ // goes away along with the function that was supposed to be called,
+ // and then later when the DLL CRT shuts down it unloads the list and
+ // tries to call the long-gone function.
+ // This is DinkumWare's implementation problem. If you encounter this
+ // problem, you may replace the calls here with good old isspace() and
+ // iswspace() from the CRT unless they specify SS_ANSI
+
+#ifdef SS_NO_LOCALE
+
+ bool operator() (CT t) const { return !ssisspace(t); }
+
+#else
+ const std::locale loc;
+ NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {}
+ bool operator() (CT t) const { return !std::isspace(t, loc); }
+#endif
+};
+
+
+
+
+// Now we can define the template (finally!)
+// =============================================================================
+// TEMPLATE: CStdStr
+// template<typename CT> class CStdStr : public std::basic_string<CT>
+//
+// REMARKS:
+// This template derives from basic_string<CT> and adds some MFC CString-
+// like functionality
+//
+// Basically, this is my attempt to make Standard C++ library strings as
+// easy to use as the MFC CString class.
+//
+// Note that although this is a template, it makes the assumption that the
+// template argument (CT, the character type) is either char or wchar_t.
+// =============================================================================
+
+//#define CStdStr _SS // avoid compiler warning 4786
+
+// template<typename ARG> ARG& FmtArg(ARG& arg) { return arg; }
+// PCSTR FmtArg(const std::string& arg) { return arg.c_str(); }
+// PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }
+
+template<typename ARG>
+struct FmtArg
+{
+ explicit FmtArg(const ARG& arg) : a_(arg) {}
+ const ARG& operator()() const { return a_; }
+ const ARG& a_;
+private:
+ FmtArg& operator=(const FmtArg&) { return *this; }
+};
+
+template<typename CT>
+class CStdStr : public std::basic_string<CT>
+{
+ // Typedefs for shorter names. Using these names also appears to help
+ // us avoid some ambiguities that otherwise arise on some platforms
+
+ #define MYBASE std::basic_string<CT> // my base class
+ //typedef typename std::basic_string<CT> MYBASE; // my base class
+ typedef CStdStr<CT> MYTYPE; // myself
+ typedef typename MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR
+ typedef typename MYBASE::pointer PMYSTR; // PSTR or PWSTR
+ typedef typename MYBASE::iterator MYITER; // my iterator type
+ typedef typename MYBASE::const_iterator MYCITER; // you get the idea...
+ typedef typename MYBASE::reverse_iterator MYRITER;
+ typedef typename MYBASE::size_type MYSIZE;
+ typedef typename MYBASE::value_type MYVAL;
+ typedef typename MYBASE::allocator_type MYALLOC;
+
+public:
+ // shorthand conversion from PCTSTR to string resource ID
+ #define SSRES(pctstr) LOWORD(reinterpret_cast<unsigned long>(pctstr))
+
+ bool TryLoad(const void* pT)
+ {
+ bool bLoaded = false;
+
+#if defined(SS_WIN32) && !defined(SS_ANSI)
+ if ( ( pT != NULL ) && SS_IS_INTRESOURCE(pT) )
+ {
+ UINT nId = LOWORD(reinterpret_cast<unsigned long>(pT));
+ if ( !LoadString(nId) )
+ {
+ TRACE(_T("Can't load string %u\n"), SSRES(pT));
+ }
+ bLoaded = true;
+ }
+#endif
+
+ return bLoaded;
+ }
+
+
+ // CStdStr inline constructors
+ CStdStr()
+ {
+ }
+
+ CStdStr(const MYTYPE& str) : MYBASE(SSREF(str))
+ {
+ }
+
+ CStdStr(const std::string& str)
+ {
+ ssasn(*this, SSREF(str));
+ }
+
+ CStdStr(const std::wstring& str)
+ {
+ ssasn(*this, SSREF(str));
+ }
+
+ CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(pT, n)
+ {
+ }
+
+#ifdef SS_UNSIGNED
+ CStdStr(PCUSTR pU)
+ {
+ *this = reinterpret_cast<PCSTR>(pU);
+ }
+#endif
+
+ CStdStr(PCSTR pA)
+ {
+ #ifdef SS_ANSI
+ *this = pA;
+ #else
+ if ( !TryLoad(pA) )
+ *this = pA;
+ #endif
+ }
+
+ CStdStr(PCWSTR pW)
+ {
+ #ifdef SS_ANSI
+ *this = pW;
+ #else
+ if ( !TryLoad(pW) )
+ *this = pW;
+ #endif
+ }
+
+ CStdStr(uint16_t* pW)
+ {
+ #ifdef SS_ANSI
+ *this = pW;
+ #else
+ if ( !TryLoad(pW) )
+ *this = pW;
+ #endif
+ }
+
+ CStdStr(uint32_t* pW)
+ {
+ #ifdef SS_ANSI
+ *this = pW;
+ #else
+ if ( !TryLoad(pW) )
+ *this = pW;
+ #endif
+ }
+
+ CStdStr(MYCITER first, MYCITER last)
+ : MYBASE(first, last)
+ {
+ }
+
+ CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())
+ : MYBASE(nSize, ch, al)
+ {
+ }
+
+ #ifdef SS_INC_COMDEF
+ CStdStr(const _bstr_t& bstr)
+ {
+ if ( bstr.length() > 0 )
+ this->append(static_cast<PCMYSTR>(bstr), bstr.length());
+ }
+ #endif
+
+ // CStdStr inline assignment operators -- the ssasn function now takes care
+ // of fixing the MSVC assignment bug (see knowledge base article Q172398).
+ MYTYPE& operator=(const MYTYPE& str)
+ {
+ ssasn(*this, str);
+ return *this;
+ }
+
+ MYTYPE& operator=(const std::string& str)
+ {
+ ssasn(*this, str);
+ return *this;
+ }
+
+ MYTYPE& operator=(const std::wstring& str)
+ {
+ ssasn(*this, str);
+ return *this;
+ }
+
+ MYTYPE& operator=(PCSTR pA)
+ {
+ ssasn(*this, pA);
+ return *this;
+ }
+
+ MYTYPE& operator=(PCWSTR pW)
+ {
+ ssasn(*this, pW);
+ return *this;
+ }
+
+#ifdef SS_UNSIGNED
+ MYTYPE& operator=(PCUSTR pU)
+ {
+ ssasn(*this, reinterpret_cast<PCSTR>(pU));
+ return *this;
+ }
+#endif
+
+ MYTYPE& operator=(uint16_t* pA)
+ {
+ ssasn(*this, pA);
+ return *this;
+ }
+
+ MYTYPE& operator=(uint32_t* pA)
+ {
+ ssasn(*this, pA);
+ return *this;
+ }
+
+ MYTYPE& operator=(CT t)
+ {
+ Q172398(*this);
+ this->assign(1, t);
+ return *this;
+ }
+
+ #ifdef SS_INC_COMDEF
+ MYTYPE& operator=(const _bstr_t& bstr)
+ {
+ if ( bstr.length() > 0 )
+ {
+ this->assign(static_cast<PCMYSTR>(bstr), bstr.length());
+ return *this;
+ }
+ else
+ {
+ this->erase();
+ return *this;
+ }
+ }
+ #endif
+
+
+ // Overloads also needed to fix the MSVC assignment bug (KB: Q172398)
+ // *** Thanks to Pete The Plumber for catching this one ***
+ // They also are compiled if you have explicitly turned off refcounting
+ #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT)
+
+ MYTYPE& assign(const MYTYPE& str)
+ {
+ Q172398(*this);
+ sscpy(GetBuffer(str.size()+1), SSREF(str));
+ this->ReleaseBuffer(str.size());
+ return *this;
+ }
+
+ MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars)
+ {
+ // This overload of basic_string::assign is supposed to assign up to
+ // <nChars> or the NULL terminator, whichever comes first. Since we
+ // are about to call a less forgiving overload (in which <nChars>
+ // must be a valid length), we must adjust the length here to a safe
+ // value. Thanks to Ullrich Poll�hne for catching this bug
+
+ nChars = SSMIN(nChars, str.length() - nStart);
+ MYTYPE strTemp(str.c_str()+nStart, nChars);
+ Q172398(*this);
+ this->assign(strTemp);
+ return *this;
+ }
+
+ MYTYPE& assign(const MYBASE& str)
+ {
+ ssasn(*this, str);
+ return *this;
+ }
+
+ MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE nChars)
+ {
+ // This overload of basic_string::assign is supposed to assign up to
+ // <nChars> or the NULL terminator, whichever comes first. Since we
+ // are about to call a less forgiving overload (in which <nChars>
+ // must be a valid length), we must adjust the length here to a safe
+ // value. Thanks to Ullrich Poll�hne for catching this bug
+
+ nChars = SSMIN(nChars, str.length() - nStart);
+
+ // Watch out for assignment to self
+
+ if ( this == &str )
+ {
+ MYTYPE strTemp(str.c_str() + nStart, nChars);
+ static_cast<MYBASE*>(this)->assign(strTemp);
+ }
+ else
+ {
+ Q172398(*this);
+ static_cast<MYBASE*>(this)->assign(str.c_str()+nStart, nChars);
+ }
+ return *this;
+ }
+
+ MYTYPE& assign(const CT* pC, MYSIZE nChars)
+ {
+ // Q172398 only fix -- erase before assigning, but not if we're
+ // assigning from our own buffer
+
+ #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
+ if ( !this->empty() &&
+ ( pC < this->data() || pC > this->data() + this->capacity() ) )
+ {
+ this->erase();
+ }
+ #endif
+ Q172398(*this);
+ static_cast<MYBASE*>(this)->assign(pC, nChars);
+ return *this;
+ }
+
+ MYTYPE& assign(MYSIZE nChars, MYVAL val)
+ {
+ Q172398(*this);
+ static_cast<MYBASE*>(this)->assign(nChars, val);
+ return *this;
+ }
+
+ MYTYPE& assign(const CT* pT)
+ {
+ return this->assign(pT, MYBASE::traits_type::length(pT));
+ }
+
+ MYTYPE& assign(MYCITER iterFirst, MYCITER iterLast)
+ {
+ #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
+ // Q172398 fix. don't call erase() if we're assigning from ourself
+ if ( iterFirst < this->begin() ||
+ iterFirst > this->begin() + this->size() )
+ {
+ this->erase()
+ }
+ #endif
+ this->replace(this->begin(), this->end(), iterFirst, iterLast);
+ return *this;
+ }
+ #endif
+
+
+ // -------------------------------------------------------------------------
+ // CStdStr inline concatenation.
+ // -------------------------------------------------------------------------
+ MYTYPE& operator+=(const MYTYPE& str)
+ {
+ ssadd(*this, str);
+ return *this;
+ }
+
+ MYTYPE& operator+=(const std::string& str)
+ {
+ ssadd(*this, str);
+ return *this;
+ }
+
+ MYTYPE& operator+=(const std::wstring& str)
+ {
+ ssadd(*this, str);
+ return *this;
+ }
+
+ MYTYPE& operator+=(PCSTR pA)
+ {
+ ssadd(*this, pA);
+ return *this;
+ }
+
+ MYTYPE& operator+=(PCWSTR pW)
+ {
+ ssadd(*this, pW);
+ return *this;
+ }
+
+ MYTYPE& operator+=(uint16_t* pW)
+ {
+ ssadd(*this, pW);
+ return *this;
+ }
+
+ MYTYPE& operator+=(uint32_t* pW)
+ {
+ ssadd(*this, pW);
+ return *this;
+ }
+
+ MYTYPE& operator+=(CT t)
+ {
+ this->append(1, t);
+ return *this;
+ }
+ #ifdef SS_INC_COMDEF // if we have _bstr_t, define a += for it too.
+ MYTYPE& operator+=(const _bstr_t& bstr)
+ {
+ return this->operator+=(static_cast<PCMYSTR>(bstr));
+ }
+ #endif
+
+
+ // -------------------------------------------------------------------------
+ // Case changing functions
+ // -------------------------------------------------------------------------
+
+ MYTYPE& ToUpper(const std::locale& loc=std::locale())
+ {
+ // Note -- if there are any MBCS character sets in which the lowercase
+ // form a character takes up a different number of bytes than the
+ // uppercase form, this would probably not work...
+
+ std::transform(this->begin(),
+ this->end(),
+ this->begin(),
+#ifdef SS_NO_LOCALE
+ SSToUpper<CT>());
+#else
+ std::bind2nd(SSToUpper<CT>(), loc));
+#endif
+
+ // ...but if it were, this would probably work better. Also, this way
+ // seems to be a bit faster when anything other then the "C" locale is
+ // used...
+
+// if ( !empty() )
+// {
+// ssupr(this->GetBuf(), this->size(), loc);
+// this->RelBuf();
+// }
+
+ return *this;
+ }
+
+ MYTYPE& ToLower(const std::locale& loc=std::locale())
+ {
+ // Note -- if there are any MBCS character sets in which the lowercase
+ // form a character takes up a different number of bytes than the
+ // uppercase form, this would probably not work...
+
+ std::transform(this->begin(),
+ this->end(),
+ this->begin(),
+#ifdef SS_NO_LOCALE
+ SSToLower<CT>());
+#else
+ std::bind2nd(SSToLower<CT>(), loc));
+#endif
+
+ // ...but if it were, this would probably work better. Also, this way
+ // seems to be a bit faster when anything other then the "C" locale is
+ // used...
+
+// if ( !empty() )
+// {
+// sslwr(this->GetBuf(), this->size(), loc);
+// this->RelBuf();
+// }
+ return *this;
+ }
+
+
+ MYTYPE& Normalize()
+ {
+ return Trim().ToLower();
+ }
+
+
+ // -------------------------------------------------------------------------
+ // CStdStr -- Direct access to character buffer. In the MS' implementation,
+ // the at() function that we use here also calls _Freeze() providing us some
+ // protection from multithreading problems associated with ref-counting.
+ // In VC 7 and later, of course, the ref-counting stuff is gone.
+ // -------------------------------------------------------------------------
+
+ CT* GetBuf(int nMinLen=-1)
+ {
+ if ( static_cast<int>(this->size()) < nMinLen )
+ this->resize(static_cast<MYSIZE>(nMinLen));
+
+ return this->empty() ? const_cast<CT*>(this->data()) : &(this->at(0));
+ }
+
+ CT* SetBuf(int nLen)
+ {
+ nLen = ( nLen > 0 ? nLen : 0 );
+ if ( this->capacity() < 1 && nLen == 0 )
+ this->resize(1);
+
+ this->resize(static_cast<MYSIZE>(nLen));
+ return const_cast<CT*>(this->data());
+ }
+ void RelBuf(int nNewLen=-1)
+ {
+ this->resize(static_cast<MYSIZE>(nNewLen > -1 ? nNewLen :
+ sslen(this->c_str())));
+ }
+
+ void BufferRel() { RelBuf(); } // backwards compatability
+ CT* Buffer() { return GetBuf(); } // backwards compatability
+ CT* BufferSet(int nLen) { return SetBuf(nLen);}// backwards compatability
+
+ bool Equals(const CT* pT, bool bUseCase=false) const
+ {
+ return 0 == (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT));
+ }
+
+ // -------------------------------------------------------------------------
+ // FUNCTION: CStdStr::Load
+ // REMARKS:
+ // Loads string from resource specified by nID
+ //
+ // PARAMETERS:
+ // nID - resource Identifier. Purely a Win32 thing in this case
+ //
+ // RETURN VALUE:
+ // true if successful, false otherwise
+ // -------------------------------------------------------------------------
+
+#ifndef SS_ANSI
+
+ bool Load(UINT nId, HMODULE hModule=NULL)
+ {
+ bool bLoaded = false; // set to true of we succeed.
+
+ #ifdef _MFC_VER // When in Rome (or MFC land)...
+
+ // If they gave a resource handle, use it. Note - this is archaic
+ // and not really what I would recommend. But then again, in MFC
+ // land, you ought to be using CString for resources anyway since
+ // it walks the resource chain for you.
+
+ HMODULE hModuleOld = NULL;
+
+ if ( NULL != hModule )
+ {
+ hModuleOld = AfxGetResourceHandle();
+ AfxSetResourceHandle(hModule);
+ }
+
+ // ...load the string
+
+ CString strRes;
+ bLoaded = FALSE != strRes.LoadString(nId);
+
+ // ...and if we set the resource handle, restore it.
+
+ if ( NULL != hModuleOld )
+ AfxSetResourceHandle(hModule);
+
+ if ( bLoaded )
+ *this = strRes;
+
+ #else // otherwise make our own hackneyed version of CString's Load
+
+ // Get the resource name and module handle
+
+ if ( NULL == hModule )
+ hModule = GetResourceHandle();
+
+ PCTSTR szName = MAKEINTRESOURCE((nId>>4)+1); // lifted
+ DWORD dwSize = 0;
+
+ // No sense continuing if we can't find the resource
+
+ HRSRC hrsrc = ::FindResource(hModule, szName, RT_STRING);
+
+ if ( NULL == hrsrc )
+ {
+ TRACE(_T("Cannot find resource %d: 0x%X"), nId, ::GetLastError());
+ }
+ else if ( 0 == (dwSize = ::SizeofResource(hModule, hrsrc) / sizeof(CT)))
+ {
+ TRACE(_T("Cant get size of resource %d 0x%X\n"),nId,GetLastError());
+ }
+ else
+ {
+ bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize);
+ ReleaseBuffer();
+ }
+
+ #endif // #ifdef _MFC_VER
+
+ if ( !bLoaded )
+ TRACE(_T("String not loaded 0x%X\n"), ::GetLastError());
+
+ return bLoaded;
+ }
+
+#endif // #ifdef SS_ANSI
+
+ // -------------------------------------------------------------------------
+ // FUNCTION: CStdStr::Format
+ // void _cdecl Formst(CStdStringA& PCSTR szFormat, ...)
+ // void _cdecl Format(PCSTR szFormat);
+ //
+ // DESCRIPTION:
+ // This function does sprintf/wsprintf style formatting on CStdStringA
+ // objects. It looks a lot like MFC's CString::Format. Some people
+ // might even call this identical. Fortunately, these people are now
+ // dead... heh heh.
+ //
+ // PARAMETERS:
+ // nId - ID of string resource holding the format string
+ // szFormat - a PCSTR holding the format specifiers
+ // argList - a va_list holding the arguments for the format specifiers.
+ //
+ // RETURN VALUE: None.
+ // -------------------------------------------------------------------------
+ // formatting (using wsprintf style formatting)
+
+ // If they want a Format() function that safely handles string objects
+ // without casting
+
+#ifdef SS_SAFE_FORMAT
+
+ // Question: Joe, you wacky coder you, why do you have so many overloads
+ // of the Format() function
+ // Answer: One reason only - CString compatability. In short, by making
+ // the Format() function a template this way, I can do strong typing
+ // and allow people to pass CStdString arguments as fillers for
+ // "%s" format specifiers without crashing their program! The downside
+ // is that I need to overload on the number of arguments. If you are
+ // passing more arguments than I have listed below in any of my
+ // overloads, just add another one.
+ //
+ // Yes, yes, this is really ugly. In essence what I am doing here is
+ // protecting people from a bad (and incorrect) programming practice
+ // that they should not be doing anyway. I am protecting them from
+ // themselves. Why am I doing this? Well, if you had any idea the
+ // number of times I've been emailed by people about this
+ // "incompatability" in my code, you wouldn't ask.
+
+ void Fmt(const CT* szFmt, ...)
+ {
+ va_list argList;
+ va_start(argList, szFmt);
+ FormatV(szFmt, argList);
+ va_end(argList);
+ }
+
+#ifndef SS_ANSI
+
+ void Format(UINT nId)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ this->swap(strFmt);
+ }
+ template<class A1>
+ void Format(UINT nId, const A1& v)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ Fmt(strFmt, FmtArg<A1>(v)());
+ }
+ template<class A1, class A2>
+ void Format(UINT nId, const A1& v1, const A2& v2)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)());
+ }
+ template<class A1, class A2, class A3>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(),FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(),FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(),FmtArg<A10>(v10)(),FmtArg<A11>(v11)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(), FmtArg<A13>(v13)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(), FmtArg<A13>(v13)(),FmtArg<A14>(v14)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14, class A15>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
+ FmtArg<A15>(v15)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14, class A15, class A16>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,
+ const A16& v16)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
+ FmtArg<A15>(v15)(), FmtArg<A16>(v16)());
+ }
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14, class A15, class A16, class A17>
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,
+ const A16& v16, const A17& v17)
+ {
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ {
+ Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
+ FmtArg<A15>(v15)(),FmtArg<A16>(v16)(),FmtArg<A17>(v17)());
+ }
+ }
+
+#endif // #ifndef SS_ANSI
+
+ // ...now the other overload of Format: the one that takes a string literal
+
+ void Format(const CT* szFmt)
+ {
+ *this = szFmt;
+ }
+ template<class A1>
+ void Format(const CT* szFmt, const A1& v)
+ {
+ Fmt(szFmt, FmtArg<A1>(v)());
+ }
+ template<class A1, class A2>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)());
+ }
+ template<class A1, class A2, class A3>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)());
+ }
+ template<class A1, class A2, class A3, class A4>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(),FmtArg<A10>(v10)(),FmtArg<A11>(v11)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(), FmtArg<A13>(v13)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(), FmtArg<A13>(v13)(),FmtArg<A14>(v14)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14, class A15>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
+ FmtArg<A15>(v15)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14, class A15, class A16>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,
+ const A16& v16)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
+ FmtArg<A15>(v15)(), FmtArg<A16>(v16)());
+ }
+ template<class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9, class A10, class A11, class A12,
+ class A13, class A14, class A15, class A16, class A17>
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,
+ const A16& v16, const A17& v17)
+ {
+ Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
+ FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
+ FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
+ FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
+ FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
+ FmtArg<A15>(v15)(),FmtArg<A16>(v16)(),FmtArg<A17>(v17)());
+ }
+
+#else // #ifdef SS_SAFE_FORMAT
+
+
+#ifndef SS_ANSI
+
+ void Format(UINT nId, ...)
+ {
+ va_list argList;
+ va_start(argList, nId);
+
+ MYTYPE strFmt;
+ if ( strFmt.Load(nId) )
+ FormatV(strFmt, argList);
+
+ va_end(argList);
+ }
+
+#endif // #ifdef SS_ANSI
+
+ void Format(const CT* szFmt, ...)
+ {
+ va_list argList;
+ va_start(argList, szFmt);
+ FormatV(szFmt, argList);
+ va_end(argList);
+ }
+
+#endif // #ifdef SS_SAFE_FORMAT
+
+ void AppendFormat(const CT* szFmt, ...)
+ {
+ va_list argList;
+ va_start(argList, szFmt);
+ AppendFormatV(szFmt, argList);
+ va_end(argList);
+ }
+
+ #define MAX_FMT_TRIES 5 // #of times we try
+ #define FMT_BLOCK_SIZE 2048 // # of bytes to increment per try
+ #define BUFSIZE_1ST 256
+ #define BUFSIZE_2ND 512
+ #define STD_BUF_SIZE 1024
+
+ // an efficient way to add formatted characters to the string. You may only
+ // add up to STD_BUF_SIZE characters at a time, though
+ void AppendFormatV(const CT* szFmt, va_list argList)
+ {
+ CT szBuf[STD_BUF_SIZE];
+ int nLen = ssnprintf(szBuf, STD_BUF_SIZE-1, szFmt, argList);
+
+ if ( 0 < nLen )
+ this->append(szBuf, nLen);
+ }
+
+ // -------------------------------------------------------------------------
+ // FUNCTION: FormatV
+ // void FormatV(PCSTR szFormat, va_list, argList);
+ //
+ // DESCRIPTION:
+ // This function formats the string with sprintf style format-specs.
+ // It makes a general guess at required buffer size and then tries
+ // successively larger buffers until it finds one big enough or a
+ // threshold (MAX_FMT_TRIES) is exceeded.
+ //
+ // PARAMETERS:
+ // szFormat - a PCSTR holding the format of the output
+ // argList - a Microsoft specific va_list for variable argument lists
+ //
+ // RETURN VALUE:
+ // -------------------------------------------------------------------------
+
+ // NOTE: Changed by JM to actually function under non-win32,
+ // and to remove the upper limit on size.
+ void FormatV(const CT* szFormat, va_list argList)
+ {
+ // try and grab a sufficient buffersize
+ int nChars = FMT_BLOCK_SIZE;
+ va_list argCopy;
+
+ CT *p = reinterpret_cast<CT*>(malloc(sizeof(CT)*nChars));
+ if (!p) return;
+
+ while (1)
+ {
+ va_copy(argCopy, argList);
+
+ int nActual = ssvsprintf(p, nChars, szFormat, argCopy);
+ /* If that worked, return the string. */
+ if (nActual > -1 && nActual < nChars)
+ { /* make sure it's NULL terminated */
+ p[nActual] = '\0';
+ this->assign(p, nActual);
+ free(p);
+ va_end(argCopy);
+ return;
+ }
+ /* Else try again with more space. */
+ if (nActual > -1) /* glibc 2.1 */
+ nChars = nActual + 1; /* precisely what is needed */
+ else /* glibc 2.0 */
+ nChars *= 2; /* twice the old size */
+
+ CT *np = reinterpret_cast<CT*>(realloc(p, sizeof(CT)*nChars));
+ if (np == NULL)
+ {
+ free(p);
+ va_end(argCopy);
+ return; // failed :(
+ }
+ p = np;
+ va_end(argCopy);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // CString Facade Functions:
+ //
+ // The following methods are intended to allow you to use this class as a
+ // near drop-in replacement for CString.
+ // -------------------------------------------------------------------------
+ #ifdef SS_WIN32
+ BSTR AllocSysString() const
+ {
+ ostring os;
+ ssasn(os, *this);
+ return ::SysAllocString(os.c_str());
+ }
+ #endif
+
+#ifndef SS_NO_LOCALE
+ int Collate(PCMYSTR szThat) const
+ {
+ return sscoll(this->c_str(), this->length(), szThat, sslen(szThat));
+ }
+
+ int CollateNoCase(PCMYSTR szThat) const
+ {
+ return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat));
+ }
+#endif
+ int Compare(PCMYSTR szThat) const
+ {
+ return this->compare(szThat);
+ }
+
+ int CompareNoCase(PCMYSTR szThat) const
+ {
+ return ssicmp(this->c_str(), szThat);
+ }
+
+ int Delete(int nIdx, int nCount=1)
+ {
+ if ( nIdx < 0 )
+ nIdx = 0;
+
+ if ( nIdx < this->GetLength() )
+ this->erase(static_cast<MYSIZE>(nIdx), static_cast<MYSIZE>(nCount));
+
+ return GetLength();
+ }
+
+ void Empty()
+ {
+ this->erase();
+ }
+
+ int Find(CT ch) const
+ {
+ MYSIZE nIdx = this->find_first_of(ch);
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+ int Find(PCMYSTR szSub) const
+ {
+ MYSIZE nIdx = this->find(szSub);
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+ int Find(CT ch, int nStart) const
+ {
+ // CString::Find docs say add 1 to nStart when it's not zero
+ // CString::Find code doesn't do that however. We'll stick
+ // with what the code does
+
+ MYSIZE nIdx = this->find_first_of(ch, static_cast<MYSIZE>(nStart));
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+ int Find(PCMYSTR szSub, int nStart) const
+ {
+ // CString::Find docs say add 1 to nStart when it's not zero
+ // CString::Find code doesn't do that however. We'll stick
+ // with what the code does
+
+ MYSIZE nIdx = this->find(szSub, static_cast<MYSIZE>(nStart));
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+ int FindOneOf(PCMYSTR szCharSet) const
+ {
+ MYSIZE nIdx = this->find_first_of(szCharSet);
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+#ifndef SS_ANSI
+ void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception)
+ {
+ va_list argList;
+ va_start(argList, szFormat);
+ PMYSTR szTemp;
+ if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ szFormat, 0, 0,
+ reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||
+ szTemp == 0 )
+ {
+ throw std::runtime_error("out of memory");
+ }
+ *this = szTemp;
+ LocalFree(szTemp);
+ va_end(argList);
+ }
+
+ void FormatMessage(UINT nFormatId, ...) throw(std::exception)
+ {
+ MYTYPE sFormat;
+ VERIFY(sFormat.LoadString(nFormatId));
+ va_list argList;
+ va_start(argList, nFormatId);
+ PMYSTR szTemp;
+ if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ sFormat, 0, 0,
+ reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||
+ szTemp == 0)
+ {
+ throw std::runtime_error("out of memory");
+ }
+ *this = szTemp;
+ LocalFree(szTemp);
+ va_end(argList);
+ }
+#endif
+
+ // GetAllocLength -- an MSVC7 function but it costs us nothing to add it.
+
+ int GetAllocLength()
+ {
+ return static_cast<int>(this->capacity());
+ }
+
+ // -------------------------------------------------------------------------
+ // GetXXXX -- Direct access to character buffer
+ // -------------------------------------------------------------------------
+ CT GetAt(int nIdx) const
+ {
+ return this->at(static_cast<MYSIZE>(nIdx));
+ }
+
+ CT* GetBuffer(int nMinLen=-1)
+ {
+ return GetBuf(nMinLen);
+ }
+
+ CT* GetBufferSetLength(int nLen)
+ {
+ return BufferSet(nLen);
+ }
+
+ // GetLength() -- MFC docs say this is the # of BYTES but
+ // in truth it is the number of CHARACTERs (chars or wchar_ts)
+ int GetLength() const
+ {
+ return static_cast<int>(this->length());
+ }
+
+ int Insert(int nIdx, CT ch)
+ {
+ if ( static_cast<MYSIZE>(nIdx) > this->size()-1 )
+ this->append(1, ch);
+ else
+ this->insert(static_cast<MYSIZE>(nIdx), 1, ch);
+
+ return GetLength();
+ }
+ int Insert(int nIdx, PCMYSTR sz)
+ {
+ if ( static_cast<MYSIZE>(nIdx) >= this->size() )
+ this->append(sz, static_cast<MYSIZE>(sslen(sz)));
+ else
+ this->insert(static_cast<MYSIZE>(nIdx), sz);
+
+ return GetLength();
+ }
+
+ bool IsEmpty() const
+ {
+ return this->empty();
+ }
+
+ MYTYPE Left(int nCount) const
+ {
+ // Range check the count.
+
+ nCount = SSMAX(0, SSMIN(nCount, static_cast<int>(this->size())));
+ return this->substr(0, static_cast<MYSIZE>(nCount));
+ }
+
+#ifndef SS_ANSI
+ bool LoadString(UINT nId)
+ {
+ return this->Load(nId);
+ }
+#endif
+
+ void MakeLower()
+ {
+ ToLower();
+ }
+
+ void MakeReverse()
+ {
+ std::reverse(this->begin(), this->end());
+ }
+
+ void MakeUpper()
+ {
+ ToUpper();
+ }
+
+ MYTYPE Mid(int nFirst) const
+ {
+ return Mid(nFirst, this->GetLength()-nFirst);
+ }
+
+ MYTYPE Mid(int nFirst, int nCount) const
+ {
+ // CString does range checking here. Since we're trying to emulate it,
+ // we must check too.
+
+ if ( nFirst < 0 )
+ nFirst = 0;
+ if ( nCount < 0 )
+ nCount = 0;
+
+ int nSize = static_cast<int>(this->size());
+
+ if ( nFirst + nCount > nSize )
+ nCount = nSize - nFirst;
+
+ if ( nFirst > nSize )
+ return MYTYPE();
+
+ ASSERT(nFirst >= 0);
+ ASSERT(nFirst + nCount <= nSize);
+
+ return this->substr(static_cast<MYSIZE>(nFirst),
+ static_cast<MYSIZE>(nCount));
+ }
+
+ void ReleaseBuffer(int nNewLen=-1)
+ {
+ RelBuf(nNewLen);
+ }
+
+ int Remove(CT ch)
+ {
+ MYSIZE nIdx = 0;
+ int nRemoved = 0;
+ while ( (nIdx=this->find_first_of(ch)) != MYBASE::npos )
+ {
+ this->erase(nIdx, 1);
+ nRemoved++;
+ }
+ return nRemoved;
+ }
+
+ int Replace(CT chOld, CT chNew)
+ {
+ int nReplaced = 0;
+
+ for ( MYITER iter=this->begin(); iter != this->end(); iter++ )
+ {
+ if ( *iter == chOld )
+ {
+ *iter = chNew;
+ nReplaced++;
+ }
+ }
+
+ return nReplaced;
+ }
+
+ int Replace(PCMYSTR szOld, PCMYSTR szNew)
+ {
+ int nReplaced = 0;
+ MYSIZE nIdx = 0;
+ MYSIZE nOldLen = sslen(szOld);
+
+ if ( 0 != nOldLen )
+ {
+ // If the replacement string is longer than the one it replaces, this
+ // string is going to have to grow in size, Figure out how much
+ // and grow it all the way now, rather than incrementally
+
+ MYSIZE nNewLen = sslen(szNew);
+ if ( nNewLen > nOldLen )
+ {
+ int nFound = 0;
+ while ( nIdx < this->length() &&
+ (nIdx=this->find(szOld, nIdx)) != MYBASE::npos )
+ {
+ nFound++;
+ nIdx += nOldLen;
+ }
+ this->reserve(this->size() + nFound * (nNewLen - nOldLen));
+ }
+
+
+ static const CT ch = CT(0);
+ PCMYSTR szRealNew = szNew == 0 ? &ch : szNew;
+ nIdx = 0;
+
+ while ( nIdx < this->length() &&
+ (nIdx=this->find(szOld, nIdx)) != MYBASE::npos )
+ {
+ this->replace(this->begin()+nIdx, this->begin()+nIdx+nOldLen,
+ szRealNew);
+
+ nReplaced++;
+ nIdx += nNewLen;
+ }
+ }
+
+ return nReplaced;
+ }
+
+ int ReverseFind(CT ch) const
+ {
+ MYSIZE nIdx = this->find_last_of(ch);
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+ // ReverseFind overload that's not in CString but might be useful
+ int ReverseFind(PCMYSTR szFind, MYSIZE pos=MYBASE::npos) const
+ {
+ //yuvalt - this does not compile with g++ since MYTTYPE() is different type
+ //MYSIZE nIdx = this->rfind(0 == szFind ? MYTYPE() : szFind, pos);
+ MYSIZE nIdx = this->rfind(0 == szFind ? "" : szFind, pos);
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
+ }
+
+ MYTYPE Right(int nCount) const
+ {
+ // Range check the count.
+
+ nCount = SSMAX(0, SSMIN(nCount, static_cast<int>(this->size())));
+ return this->substr(this->size()-static_cast<MYSIZE>(nCount));
+ }
+
+ void SetAt(int nIndex, CT ch)
+ {
+ ASSERT(this->size() > static_cast<MYSIZE>(nIndex));
+ this->at(static_cast<MYSIZE>(nIndex)) = ch;
+ }
+
+#ifndef SS_ANSI
+ BSTR SetSysString(BSTR* pbstr) const
+ {
+ ostring os;
+ ssasn(os, *this);
+ if ( !::SysReAllocStringLen(pbstr, os.c_str(), os.length()) )
+ throw std::runtime_error("out of memory");
+
+ ASSERT(*pbstr != 0);
+ return *pbstr;
+ }
+#endif
+
+ MYTYPE SpanExcluding(PCMYSTR szCharSet) const
+ {
+ MYSIZE pos = this->find_first_of(szCharSet);
+ return pos == MYBASE::npos ? *this : Left(pos);
+ }
+
+ MYTYPE SpanIncluding(PCMYSTR szCharSet) const
+ {
+ MYSIZE pos = this->find_first_not_of(szCharSet);
+ return pos == MYBASE::npos ? *this : Left(pos);
+ }
+
+#if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI)
+
+ // CString's OemToAnsi and AnsiToOem functions are available only in
+ // Unicode builds. However since we're a template we also need a
+ // runtime check of CT and a reinterpret_cast to account for the fact
+ // that CStdStringW gets instantiated even in non-Unicode builds.
+
+ void AnsiToOem()
+ {
+ if ( sizeof(CT) == sizeof(char) && !empty() )
+ {
+ ::CharToOem(reinterpret_cast<PCSTR>(this->c_str()),
+ reinterpret_cast<PSTR>(GetBuf()));
+ }
+ else
+ {
+ ASSERT(false);
+ }
+ }
+
+ void OemToAnsi()
+ {
+ if ( sizeof(CT) == sizeof(char) && !empty() )
+ {
+ ::OemToChar(reinterpret_cast<PCSTR>(this->c_str()),
+ reinterpret_cast<PSTR>(GetBuf()));
+ }
+ else
+ {
+ ASSERT(false);
+ }
+ }
+
+#endif
+
+
+ // -------------------------------------------------------------------------
+ // Trim and its variants
+ // -------------------------------------------------------------------------
+ MYTYPE& Trim()
+ {
+ return TrimLeft().TrimRight();
+ }
+
+ MYTYPE& TrimLeft()
+ {
+ this->erase(this->begin(),
+ std::find_if(this->begin(), this->end(), NotSpace<CT>()));
+
+ return *this;
+ }
+
+ MYTYPE& TrimLeft(CT tTrim)
+ {
+ this->erase(0, this->find_first_not_of(tTrim));
+ return *this;
+ }
+
+ MYTYPE& TrimLeft(PCMYSTR szTrimChars)
+ {
+ this->erase(0, this->find_first_not_of(szTrimChars));
+ return *this;
+ }
+
+ MYTYPE& TrimRight()
+ {
+ // NOTE: When comparing reverse_iterators here (MYRITER), I avoid using
+ // operator!=. This is because namespace rel_ops also has a template
+ // operator!= which conflicts with the global operator!= already defined
+ // for reverse_iterator in the header <utility>.
+ // Thanks to John James for alerting me to this.
+
+ MYRITER it = std::find_if(this->rbegin(), this->rend(), NotSpace<CT>());
+ if ( !(this->rend() == it) )
+ this->erase(this->rend() - it);
+
+ this->erase(!(it == this->rend()) ? this->find_last_of(*it) + 1 : 0);
+ return *this;
+ }
+
+ MYTYPE& TrimRight(CT tTrim)
+ {
+ MYSIZE nIdx = this->find_last_not_of(tTrim);
+ this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);
+ return *this;
+ }
+
+ MYTYPE& TrimRight(PCMYSTR szTrimChars)
+ {
+ MYSIZE nIdx = this->find_last_not_of(szTrimChars);
+ this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);
+ return *this;
+ }
+
+ void FreeExtra()
+ {
+ MYTYPE mt;
+ this->swap(mt);
+ if ( !mt.empty() )
+ this->assign(mt.c_str(), mt.size());
+ }
+
+ // I have intentionally not implemented the following CString
+ // functions. You cannot make them work without taking advantage
+ // of implementation specific behavior. However if you absolutely
+ // MUST have them, uncomment out these lines for "sort-of-like"
+ // their behavior. You're on your own.
+
+// CT* LockBuffer() { return GetBuf(); }// won't really lock
+// void UnlockBuffer(); { } // why have UnlockBuffer w/o LockBuffer?
+
+ // Array-indexing operators. Required because we defined an implicit cast
+ // to operator const CT* (Thanks to Julian Selman for pointing this out)
+
+ CT& operator[](int nIdx)
+ {
+ return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
+ }
+
+ const CT& operator[](int nIdx) const
+ {
+ return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
+ }
+
+ CT& operator[](unsigned int nIdx)
+ {
+ return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
+ }
+
+ const CT& operator[](unsigned int nIdx) const
+ {
+ return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
+ }
+
+ CT& operator[](unsigned long nIdx)
+ {
+ return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
+ }
+
+ const CT& operator[](unsigned long nIdx) const
+ {
+ return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
+ }
+
+#ifndef SS_NO_IMPLICIT_CAST
+ operator const CT*() const
+ {
+ return this->c_str();
+ }
+#endif
+
+ // IStream related functions. Useful in IPersistStream implementations
+
+#ifdef SS_INC_COMDEF
+
+ // struct SSSHDR - useful for non Std C++ persistence schemes.
+ typedef struct SSSHDR
+ {
+ BYTE byCtrl;
+ ULONG nChars;
+ } SSSHDR; // as in "Standard String Stream Header"
+
+ #define SSSO_UNICODE 0x01 // the string is a wide string
+ #define SSSO_COMPRESS 0x02 // the string is compressed
+
+ // -------------------------------------------------------------------------
+ // FUNCTION: StreamSize
+ // REMARKS:
+ // Returns how many bytes it will take to StreamSave() this CStdString
+ // object to an IStream.
+ // -------------------------------------------------------------------------
+ ULONG StreamSize() const
+ {
+ // Control header plus string
+ ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
+ return (this->size() * sizeof(CT)) + sizeof(SSSHDR);
+ }
+
+ // -------------------------------------------------------------------------
+ // FUNCTION: StreamSave
+ // REMARKS:
+ // Saves this CStdString object to a COM IStream.
+ // -------------------------------------------------------------------------
+ HRESULT StreamSave(IStream* pStream) const
+ {
+ ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
+ HRESULT hr = E_FAIL;
+ ASSERT(pStream != 0);
+ SSSHDR hdr;
+ hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0;
+ hdr.nChars = this->size();
+
+
+ if ( FAILED(hr=pStream->Write(&hdr, sizeof(SSSHDR), 0)) )
+ {
+ TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),hr);
+ }
+ else if ( empty() )
+ {
+ ; // nothing to write
+ }
+ else if ( FAILED(hr=pStream->Write(this->c_str(),
+ this->size()*sizeof(CT), 0)) )
+ {
+ TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr);
+ }
+
+ return hr;
+ }
+
+
+ // -------------------------------------------------------------------------
+ // FUNCTION: StreamLoad
+ // REMARKS:
+ // This method loads the object from an IStream.
+ // -------------------------------------------------------------------------
+ HRESULT StreamLoad(IStream* pStream)
+ {
+ ASSERT(pStream != 0);
+ SSSHDR hdr;
+ HRESULT hr = E_FAIL;
+
+ if ( FAILED(hr=pStream->Read(&hdr, sizeof(SSSHDR), 0)) )
+ {
+ TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr);
+ }
+ else if ( hdr.nChars > 0 )
+ {
+ ULONG nRead = 0;
+ PMYSTR pMyBuf = BufferSet(hdr.nChars);
+
+ // If our character size matches the character size of the string
+ // we're trying to read, then we can read it directly into our
+ // buffer. Otherwise, we have to read into an intermediate buffer
+ // and convert.
+
+ if ( (hdr.byCtrl & SSSO_UNICODE) != 0 )
+ {
+ ULONG nBytes = hdr.nChars * sizeof(wchar_t);
+ if ( sizeof(CT) == sizeof(wchar_t) )
+ {
+ if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
+ }
+ else
+ {
+ PWSTR pBufW = reinterpret_cast<PWSTR>(_alloca((nBytes)+1));
+ if ( FAILED(hr=pStream->Read(pBufW, nBytes, &nRead)) )
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
+ else
+ sscpy(pMyBuf, pBufW, hdr.nChars);
+ }
+ }
+ else
+ {
+ ULONG nBytes = hdr.nChars * sizeof(char);
+ if ( sizeof(CT) == sizeof(char) )
+ {
+ if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
+ }
+ else
+ {
+ PSTR pBufA = reinterpret_cast<PSTR>(_alloca(nBytes));
+ if ( FAILED(hr=pStream->Read(pBufA, hdr.nChars, &nRead)) )
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
+ else
+ sscpy(pMyBuf, pBufA, hdr.nChars);
+ }
+ }
+ }
+ else
+ {
+ this->erase();
+ }
+ return hr;
+ }
+#endif // #ifdef SS_INC_COMDEF
+
+#ifndef SS_ANSI
+
+ // SetResourceHandle/GetResourceHandle. In MFC builds, these map directly
+ // to AfxSetResourceHandle and AfxGetResourceHandle. In non-MFC builds they
+ // point to a single static HINST so that those who call the member
+ // functions that take resource IDs can provide an alternate HINST of a DLL
+ // to search. This is not exactly the list of HMODULES that MFC provides
+ // but it's better than nothing.
+
+ #ifdef _MFC_VER
+ static void SetResourceHandle(HMODULE hNew)
+ {
+ AfxSetResourceHandle(hNew);
+ }
+ static HMODULE GetResourceHandle()
+ {
+ return AfxGetResourceHandle();
+ }
+ #else
+ static void SetResourceHandle(HMODULE hNew)
+ {
+ SSResourceHandle() = hNew;
+ }
+ static HMODULE GetResourceHandle()
+ {
+ return SSResourceHandle();
+ }
+ #endif
+
+#endif
+};
+
+// -----------------------------------------------------------------------------
+// MSVC USERS: HOW TO EXPORT CSTDSTRING FROM A DLL
+//
+// If you are using MS Visual C++ and you want to export CStdStringA and
+// CStdStringW from a DLL, then all you need to
+//
+// 1. make sure that all components link to the same DLL version
+// of the CRT (not the static one).
+// 2. Uncomment the 3 lines of code below
+// 3. #define 2 macros per the instructions in MS KnowledgeBase
+// article Q168958. The macros are:
+//
+// MACRO DEFINTION WHEN EXPORTING DEFINITION WHEN IMPORTING
+// ----- ------------------------ -------------------------
+// SSDLLEXP (nothing, just #define it) extern
+// SSDLLSPEC __declspec(dllexport) __declspec(dllimport)
+//
+// Note that these macros must be available to ALL clients who want to
+// link to the DLL and use the class. If they
+//
+// A word of advice: Don't bother.
+//
+// Really, it is not necessary to export CStdString functions from a DLL. I
+// never do. In my projects, I do generally link to the DLL version of the
+// Standard C++ Library, but I do NOT attempt to export CStdString functions.
+// I simply include the header where it is needed and allow for the code
+// redundancy.
+//
+// That redundancy is a lot less than you think. This class does most of its
+// work via the Standard C++ Library, particularly the base_class basic_string<>
+// member functions. Most of the functions here are small enough to be inlined
+// anyway. Besides, you'll find that in actual practice you use less than 1/2
+// of the code here, even in big projects and different modules will use as
+// little as 10% of it. That means a lot less functions actually get linked
+// your binaries. If you export this code from a DLL, it ALL gets linked in.
+//
+// I've compared the size of the binaries from exporting vs NOT exporting. Take
+// my word for it -- exporting this code is not worth the hassle.
+//
+// -----------------------------------------------------------------------------
+//#pragma warning(disable:4231) // non-standard extension ("extern template")
+// SSDLLEXP template class SSDLLSPEC CStdStr<char>;
+// SSDLLEXP template class SSDLLSPEC CStdStr<wchar_t>;
+
+
+// =============================================================================
+// END OF CStdStr INLINE FUNCTION DEFINITIONS
+// =============================================================================
+
+// Now typedef our class names based upon this humongous template
+
+typedef CStdStr<char> CStdStringA; // a better std::string
+typedef CStdStr<wchar_t> CStdStringW; // a better std::wstring
+typedef CStdStr<uint16_t> CStdString16; // a 16bit char string
+typedef CStdStr<uint32_t> CStdString32; // a 32bit char string
+typedef CStdStr<OLECHAR> CStdStringO; // almost always CStdStringW
+
+// -----------------------------------------------------------------------------
+// CStdStr addition functions defined as inline
+// -----------------------------------------------------------------------------
+
+
+inline CStdStringA operator+(const CStdStringA& s1, const CStdStringA& s2)
+{
+ CStdStringA sRet(SSREF(s1));
+ sRet.append(s2);
+ return sRet;
+}
+inline CStdStringA operator+(const CStdStringA& s1, CStdStringA::value_type t)
+{
+ CStdStringA sRet(SSREF(s1));
+ sRet.append(1, t);
+ return sRet;
+}
+inline CStdStringA operator+(const CStdStringA& s1, PCSTR pA)
+{
+ CStdStringA sRet(SSREF(s1));
+ sRet.append(pA);
+ return sRet;
+}
+inline CStdStringA operator+(PCSTR pA, const CStdStringA& sA)
+{
+ CStdStringA sRet;
+ CStdStringA::size_type nObjSize = sA.size();
+ CStdStringA::size_type nLitSize =
+ static_cast<CStdStringA::size_type>(sslen(pA));
+
+ sRet.reserve(nLitSize + nObjSize);
+ sRet.assign(pA);
+ sRet.append(sA);
+ return sRet;
+}
+
+
+inline CStdStringA operator+(const CStdStringA& s1, const CStdStringW& s2)
+{
+ return s1 + CStdStringA(s2);
+}
+inline CStdStringW operator+(const CStdStringW& s1, const CStdStringW& s2)
+{
+ CStdStringW sRet(SSREF(s1));
+ sRet.append(s2);
+ return sRet;
+}
+inline CStdStringA operator+(const CStdStringA& s1, PCWSTR pW)
+{
+ return s1 + CStdStringA(pW);
+}
+
+#ifdef UNICODE
+ inline CStdStringW operator+(PCWSTR pW, const CStdStringA& sA)
+ {
+ return CStdStringW(pW) + CStdStringW(SSREF(sA));
+ }
+ inline CStdStringW operator+(PCSTR pA, const CStdStringW& sW)
+ {
+ return CStdStringW(pA) + sW;
+ }
+#else
+ inline CStdStringA operator+(PCWSTR pW, const CStdStringA& sA)
+ {
+ return CStdStringA(pW) + sA;
+ }
+ inline CStdStringA operator+(PCSTR pA, const CStdStringW& sW)
+ {
+ return pA + CStdStringA(sW);
+ }
+#endif
+
+// ...Now the wide string versions.
+inline CStdStringW operator+(const CStdStringW& s1, CStdStringW::value_type t)
+{
+ CStdStringW sRet(SSREF(s1));
+ sRet.append(1, t);
+ return sRet;
+}
+inline CStdStringW operator+(const CStdStringW& s1, PCWSTR pW)
+{
+ CStdStringW sRet(SSREF(s1));
+ sRet.append(pW);
+ return sRet;
+}
+inline CStdStringW operator+(PCWSTR pW, const CStdStringW& sW)
+{
+ CStdStringW sRet;
+ CStdStringW::size_type nObjSize = sW.size();
+ CStdStringA::size_type nLitSize =
+ static_cast<CStdStringW::size_type>(sslen(pW));
+
+ sRet.reserve(nLitSize + nObjSize);
+ sRet.assign(pW);
+ sRet.append(sW);
+ return sRet;
+}
+
+inline CStdStringW operator+(const CStdStringW& s1, const CStdStringA& s2)
+{
+ return s1 + CStdStringW(s2);
+}
+inline CStdStringW operator+(const CStdStringW& s1, PCSTR pA)
+{
+ return s1 + CStdStringW(pA);
+}
+
+
+// New-style format function is a template
+
+#ifdef SS_SAFE_FORMAT
+
+template<>
+struct FmtArg<CStdStringA>
+{
+ explicit FmtArg(const CStdStringA& arg) : a_(arg) {}
+ PCSTR operator()() const { return a_.c_str(); }
+ const CStdStringA& a_;
+private:
+ FmtArg<CStdStringA>& operator=(const FmtArg<CStdStringA>&) { return *this; }
+};
+template<>
+struct FmtArg<CStdStringW>
+{
+ explicit FmtArg(const CStdStringW& arg) : a_(arg) {}
+ PCWSTR operator()() const { return a_.c_str(); }
+ const CStdStringW& a_;
+private:
+ FmtArg<CStdStringW>& operator=(const FmtArg<CStdStringW>&) { return *this; }
+};
+
+template<>
+struct FmtArg<std::string>
+{
+ explicit FmtArg(const std::string& arg) : a_(arg) {}
+ PCSTR operator()() const { return a_.c_str(); }
+ const std::string& a_;
+private:
+ FmtArg<std::string>& operator=(const FmtArg<std::string>&) { return *this; }
+};
+template<>
+struct FmtArg<std::wstring>
+{
+ explicit FmtArg(const std::wstring& arg) : a_(arg) {}
+ PCWSTR operator()() const { return a_.c_str(); }
+ const std::wstring& a_;
+private:
+ FmtArg<std::wstring>& operator=(const FmtArg<std::wstring>&) {return *this;}
+};
+#endif // #ifdef SS_SAFEFORMAT
+
+#ifndef SS_ANSI
+ // SSResourceHandle: our MFC-like resource handle
+ inline HMODULE& SSResourceHandle()
+ {
+ static HMODULE hModuleSS = GetModuleHandle(0);
+ return hModuleSS;
+ }
+#endif
+
+
+// In MFC builds, define some global serialization operators
+// Special operators that allow us to serialize CStdStrings to CArchives.
+// Note that we use an intermediate CString object in order to ensure that
+// we use the exact same format.
+
+#ifdef _MFC_VER
+ inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringA& strA)
+ {
+ CString strTemp = strA;
+ return ar << strTemp;
+ }
+ inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringW& strW)
+ {
+ CString strTemp = strW;
+ return ar << strTemp;
+ }
+
+ inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringA& strA)
+ {
+ CString strTemp;
+ ar >> strTemp;
+ strA = strTemp;
+ return ar;
+ }
+ inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringW& strW)
+ {
+ CString strTemp;
+ ar >> strTemp;
+ strW = strTemp;
+ return ar;
+ }
+#endif // #ifdef _MFC_VER -- (i.e. is this MFC?)
+
+
+
+// -----------------------------------------------------------------------------
+// GLOBAL FUNCTION: WUFormat
+// CStdStringA WUFormat(UINT nId, ...);
+// CStdStringA WUFormat(PCSTR szFormat, ...);
+//
+// REMARKS:
+// This function allows the caller for format and return a CStdStringA
+// object with a single line of code.
+// -----------------------------------------------------------------------------
+#ifdef SS_ANSI
+#else
+ inline CStdStringA WUFormatA(UINT nId, ...)
+ {
+ va_list argList;
+ va_start(argList, nId);
+
+ CStdStringA strFmt;
+ CStdStringA strOut;
+ if ( strFmt.Load(nId) )
+ strOut.FormatV(strFmt, argList);
+
+ va_end(argList);
+ return strOut;
+ }
+ inline CStdStringA WUFormatA(PCSTR szFormat, ...)
+ {
+ va_list argList;
+ va_start(argList, szFormat);
+ CStdStringA strOut;
+ strOut.FormatV(szFormat, argList);
+ va_end(argList);
+ return strOut;
+ }
+ inline CStdStringW WUFormatW(UINT nId, ...)
+ {
+ va_list argList;
+ va_start(argList, nId);
+
+ CStdStringW strFmt;
+ CStdStringW strOut;
+ if ( strFmt.Load(nId) )
+ strOut.FormatV(strFmt, argList);
+
+ va_end(argList);
+ return strOut;
+ }
+ inline CStdStringW WUFormatW(PCWSTR szwFormat, ...)
+ {
+ va_list argList;
+ va_start(argList, szwFormat);
+ CStdStringW strOut;
+ strOut.FormatV(szwFormat, argList);
+ va_end(argList);
+ return strOut;
+ }
+#endif // #ifdef SS_ANSI
+
+
+
+#if defined(SS_WIN32) && !defined (SS_ANSI)
+ // -------------------------------------------------------------------------
+ // FUNCTION: WUSysMessage
+ // CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);
+ // CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);
+ //
+ // DESCRIPTION:
+ // This function simplifies the process of obtaining a string equivalent
+ // of a system error code returned from GetLastError(). You simply
+ // supply the value returned by GetLastError() to this function and the
+ // corresponding system string is returned in the form of a CStdStringA.
+ //
+ // PARAMETERS:
+ // dwError - a DWORD value representing the error code to be translated
+ // dwLangId - the language id to use. defaults to english.
+ //
+ // RETURN VALUE:
+ // a CStdStringA equivalent of the error code. Currently, this function
+ // only returns either English of the system default language strings.
+ // -------------------------------------------------------------------------
+ #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)
+ inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID)
+ {
+ CHAR szBuf[512];
+
+ if ( 0 != ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
+ dwLangId, szBuf, 511, NULL) )
+ return WUFormatA("%s (0x%X)", szBuf, dwError);
+ else
+ return WUFormatA("Unknown error (0x%X)", dwError);
+ }
+ inline CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID)
+ {
+ WCHAR szBuf[512];
+
+ if ( 0 != ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
+ dwLangId, szBuf, 511, NULL) )
+ return WUFormatW(L"%s (0x%X)", szBuf, dwError);
+ else
+ return WUFormatW(L"Unknown error (0x%X)", dwError);
+ }
+#endif
+
+// Define TCHAR based friendly names for some of these functions
+
+#ifdef UNICODE
+ //#define CStdString CStdStringW
+ typedef CStdStringW CStdString;
+ #define WUSysMessage WUSysMessageW
+ #define WUFormat WUFormatW
+#else
+ //#define CStdString CStdStringA
+ typedef CStdStringA CStdString;
+ #define WUSysMessage WUSysMessageA
+ #define WUFormat WUFormatA
+#endif
+
+// ...and some shorter names for the space-efficient
+
+#define WUSysMsg WUSysMessage
+#define WUSysMsgA WUSysMessageA
+#define WUSysMsgW WUSysMessageW
+#define WUFmtA WUFormatA
+#define WUFmtW WUFormatW
+#define WUFmt WUFormat
+#define WULastErrMsg() WUSysMessage(::GetLastError())
+#define WULastErrMsgA() WUSysMessageA(::GetLastError())
+#define WULastErrMsgW() WUSysMessageW(::GetLastError())
+
+
+// -----------------------------------------------------------------------------
+// FUNCTIONAL COMPARATORS:
+// REMARKS:
+// These structs are derived from the std::binary_function template. They
+// give us functional classes (which may be used in Standard C++ Library
+// collections and algorithms) that perform case-insensitive comparisons of
+// CStdString objects. This is useful for maps in which the key may be the
+// proper string but in the wrong case.
+// -----------------------------------------------------------------------------
+#define StdStringLessNoCaseW SSLNCW // avoid VC compiler warning 4786
+#define StdStringEqualsNoCaseW SSENCW
+#define StdStringLessNoCaseA SSLNCA
+#define StdStringEqualsNoCaseA SSENCA
+
+#ifdef UNICODE
+ #define StdStringLessNoCase SSLNCW
+ #define StdStringEqualsNoCase SSENCW
+#else
+ #define StdStringLessNoCase SSLNCA
+ #define StdStringEqualsNoCase SSENCA
+#endif
+
+struct StdStringLessNoCaseW
+ : std::binary_function<CStdStringW, CStdStringW, bool>
+{
+ inline
+ bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }
+};
+struct StdStringEqualsNoCaseW
+ : std::binary_function<CStdStringW, CStdStringW, bool>
+{
+ inline
+ bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }
+};
+struct StdStringLessNoCaseA
+ : std::binary_function<CStdStringA, CStdStringA, bool>
+{
+ inline
+ bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }
+};
+struct StdStringEqualsNoCaseA
+ : std::binary_function<CStdStringA, CStdStringA, bool>
+{
+ inline
+ bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }
+};
+
+// If we had to define our own version of TRACE above, get rid of it now
+
+#ifdef TRACE_DEFINED_HERE
+ #undef TRACE
+ #undef TRACE_DEFINED_HERE
+#endif
+
+
+// These std::swap specializations come courtesy of Mike Crusader.
+
+//namespace std
+//{
+// inline void swap(CStdStringA& s1, CStdStringA& s2) throw()
+// {
+// s1.swap(s2);
+// }
+// template<>
+// inline void swap(CStdStringW& s1, CStdStringW& s2) throw()
+// {
+// s1.swap(s2);
+// }
+//}
+
+// Turn back on any Borland warnings we turned off.
+
+#ifdef __BORLANDC__
+ #pragma option pop // Turn back on inline function warnings
+// #pragma warn +inl // Turn back on inline function warnings
+#endif
+
+typedef std::vector<CStdString> CStdStringArray;
+
+#endif // #ifndef STDSTRING_H
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "threads.h"
+#include <queue>
+
+template<typename _BType>
+ struct CecBuffer
+ {
+ public:
+ CecBuffer(void) {}
+ virtual ~CecBuffer(void) {}
+
+ void Push(_BType entry)
+ {
+ CLockObject lock(&mutex);
+ buffer.push(entry);
+ }
+
+ bool Pop(_BType &entry)
+ {
+ bool bReturn(false);
+ CLockObject lock(&mutex);
+ if (buffer.size() > 0)
+ {
+ entry = buffer.front();
+ buffer.pop();
+ bReturn = true;
+ }
+ return bReturn;
+ }
+
+ private:
+ std::queue<_BType> buffer;
+ CMutex mutex;
+ };
--- /dev/null
+/*
+ * boblight
+ * Copyright (C) Bob 2009
+ *
+ * boblight is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * boblight is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>
+#include <locale.h>
+#include "misc.h"
+
+using namespace std;
+
+void PrintError(const std::string& error)
+{
+ std::cerr << "ERROR: " << error << "\n";
+}
+
+//get the first word (separated by whitespace) from string data and place that in word
+//then remove that word from string data
+bool GetWord(string& data, string& word)
+{
+ stringstream datastream(data);
+ string end;
+
+ datastream >> word;
+ if (datastream.fail())
+ {
+ data.clear();
+ return false;
+ }
+
+ size_t pos = data.find(word) + word.length();
+
+ if (pos >= data.length())
+ {
+ data.clear();
+ return true;
+ }
+
+ data = data.substr(pos);
+
+ datastream.clear();
+ datastream.str(data);
+
+ datastream >> end;
+ if (datastream.fail())
+ data.clear();
+
+ return true;
+}
+
+//convert . or , to the current locale for correct conversion of ascii float
+void ConvertFloatLocale(std::string& strfloat)
+{
+ static struct lconv* locale = localeconv();
+
+ size_t pos = strfloat.find_first_of(",.");
+
+ while (pos != string::npos)
+ {
+ strfloat.replace(pos, 1, 1, *locale->decimal_point);
+ pos++;
+
+ if (pos >= strfloat.size())
+ break;
+
+ pos = strfloat.find_first_of(",.", pos);
+ }
+}
--- /dev/null
+#pragma once
+
+/*
+ * boblight
+ * Copyright (C) Bob 2009
+ *
+ * boblight is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * boblight is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string>
+#include <sstream>
+#include <exception>
+#include <stdexcept>
+
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+void PrintError(const std::string& error);
+bool GetWord(std::string& data, std::string& word);
+void ConvertFloatLocale(std::string& strfloat);
+
+template <class Value>
+inline std::string ToString(Value value)
+{
+ std::string data;
+ std::stringstream valuestream;
+ valuestream << value;
+ valuestream >> data;
+ return data;
+}
+
+inline std::string GetErrno()
+{
+ return strerror(errno);
+}
+
+inline std::string GetErrno(int err)
+{
+ return strerror(err);
+}
+
+template <class A, class B, class C>
+inline A Clamp(A value, B min, C max)
+{
+ return value < max ? (value > min ? value : min) : max;
+}
+
+template <class A, class B>
+inline A Max(A value1, B value2)
+{
+ return value1 > value2 ? value1 : value2;
+}
+
+template <class A, class B, class C>
+inline A Max(A value1, B value2, C value3)
+{
+ return (value1 > value2) ? (value1 > value3 ? value1 : value3) : (value2 > value3 ? value2 : value3);
+}
+
+template <class A, class B>
+inline A Min(A value1, B value2)
+{
+ return value1 < value2 ? value1 : value2;
+}
+
+template <class A, class B, class C>
+inline A Min(A value1, B value2, C value3)
+{
+ return (value1 < value2) ? (value1 < value3 ? value1 : value3) : (value2 < value3 ? value2 : value3);
+}
+
+template <class T>
+inline T Abs(T value)
+{
+ return value > 0 ? value : -value;
+}
+
+template <class A, class B>
+inline A Round(B value)
+{
+ if (value == 0.0)
+ {
+ return 0;
+ }
+ else if (value > 0.0)
+ {
+ return (A)(value + 0.5);
+ }
+ else
+ {
+ return (A)(value - 0.5);
+ }
+}
+
+//inline int32_t Round32(float value)
+//{
+// return lroundf(value);
+//}
+//
+//inline int32_t Round32(double value)
+//{
+// return lround(value);
+//}
+//
+//inline int64_t Round64(float value)
+//{
+// return llroundf(value);
+//}
+//
+//inline int64_t Round64(double value)
+//{
+// return llround(value);
+//}
+
+inline bool StrToInt(const std::string& data, int& value)
+{
+ return sscanf(data.c_str(), "%i", &value) == 1;
+}
+
+inline bool HexStrToInt(const std::string& data, int& value)
+{
+ return sscanf(data.c_str(), "%x", &value) == 1;
+}
+
+inline bool StrToFloat(const std::string& data, float& value)
+{
+ return sscanf(data.c_str(), "%f", &value) == 1;
+}
+
+inline bool StrToFloat(const std::string& data, double& value)
+{
+ return sscanf(data.c_str(), "%lf", &value) == 1;
+}
+
+inline bool StrToBool(const std::string& data, bool& value)
+{
+ std::string data2 = data;
+ std::string word;
+ if (!GetWord(data2, word))
+ return false;
+
+ if (word == "1" || word == "true" || word == "on" || word == "yes")
+ {
+ value = true;
+ return true;
+ }
+ else if (word == "0" || word == "false" || word == "off" || word == "no")
+ {
+ value = false;
+ return true;
+ }
+ else
+ {
+ int ivalue;
+ if (StrToInt(word, ivalue))
+ {
+ value = ivalue != 0;
+ return true;
+ }
+ }
+
+ return false;
+}
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "threads.h"
+#include "timeutils.h"
+
+CMutex::CMutex(void)
+{
+ pthread_mutex_init(&m_mutex, NULL);
+ m_condition = new CCondition();
+ m_bLocked = false;
+}
+
+CMutex::~CMutex(void)
+{
+ delete m_condition;
+ pthread_mutex_destroy(&m_mutex);
+}
+
+bool CMutex::TryLock(int64_t iTimeout)
+{
+ m_bLocked = (pthread_mutex_trylock(&m_mutex) == 0);
+ if (!m_bLocked)
+ {
+ if (m_condition->Wait(this, iTimeout))
+ m_bLocked = (pthread_mutex_trylock(&m_mutex) == 0);
+ }
+
+ return m_bLocked;
+}
+
+bool CMutex::Lock(void)
+{
+ m_bLocked = (pthread_mutex_lock(&m_mutex) == 0);
+ return m_bLocked;
+}
+
+void CMutex::Unlock(void)
+{
+ pthread_mutex_unlock(&m_mutex);
+ m_bLocked = false;
+ m_condition->Signal();
+}
+
+CLockObject::CLockObject(CMutex *mutex, int64_t iTimeout /* = -1 */) :
+ m_mutex(mutex),
+ m_bLocked(false)
+{
+ if (iTimeout > 0)
+ m_bLocked = m_mutex->TryLock(iTimeout);
+ else
+ m_bLocked = m_mutex->Lock();
+}
+
+CLockObject::~CLockObject(void)
+{
+ m_mutex->Unlock();
+ m_bLocked = false;
+ m_mutex = NULL;
+}
+
+CCondition::CCondition(void)
+{
+ pthread_cond_init(&m_cond, NULL);
+ m_bSignaled = false;
+}
+
+CCondition::~CCondition(void)
+{
+ pthread_cond_broadcast(&m_cond);
+ pthread_cond_destroy(&m_cond);
+}
+
+void CCondition::Signal(void)
+{
+ pthread_cond_broadcast(&m_cond);
+}
+
+bool CCondition::Wait(CMutex *mutex, int64_t iTimeout)
+{
+ struct timespec abstime;
+ struct timeval now;
+ if (gettimeofday(&now, NULL) == 0)
+ {
+ iTimeout += now.tv_usec / 1000;
+ abstime.tv_sec = now.tv_sec + (time_t)(iTimeout / 1000);
+ abstime.tv_nsec = (long)((iTimeout % (unsigned long)1000) * (unsigned long)1000000);
+ m_bSignaled = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0);
+ }
+
+ bool bReturn = m_bSignaled;
+ m_bSignaled = false;
+
+ return bReturn;
+}
+
+void CCondition::Sleep(int iTimeout)
+{
+ sched_yield();
+ CCondition w;
+ CMutex m;
+ w.Wait(&m, iTimeout);
+}
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "../libPlatform/os-dependent.h"
+
+class CMutex;
+
+class CCondition
+{
+public:
+ CCondition(void);
+ ~CCondition(void);
+
+ void Signal(void);
+ bool Wait(CMutex *mutex, int64_t iTimeout);
+ static void Sleep(int iTimeout);
+
+private:
+ bool m_bSignaled;
+ pthread_cond_t m_cond;
+};
+
+class CMutex
+{
+public:
+ CMutex(void);
+ virtual ~CMutex(void);
+
+ bool TryLock(int64_t iTimeout);
+ bool Lock(void);
+ void Unlock(void);
+ bool IsLocked(void) const { return m_bLocked; }
+
+ pthread_mutex_t m_mutex;
+ CCondition *m_condition;
+ bool m_bLocked;
+};
+
+class CLockObject
+{
+public:
+ CLockObject(CMutex *mutex, int64_t iTimeout = -1);
+ ~CLockObject(void);
+
+ bool IsLocked(void) const { return m_bLocked; }
+
+private:
+ CMutex *m_mutex;
+ bool m_bLocked;
+};
--- /dev/null
+#pragma once
+
+/*
+ * boblight
+ * Copyright (C) Bob 2009
+ *
+ * boblight is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * boblight is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <time.h>
+
+inline int64_t GetTimeMs()
+{
+#ifdef __WINDOWS__
+ time_t rawtime;
+ time(&rawtime);
+
+ LARGE_INTEGER tickPerSecond;
+ LARGE_INTEGER tick;
+ if (QueryPerformanceFrequency(&tickPerSecond))
+ {
+ QueryPerformanceCounter(&tick);
+ return (int64_t) (tick.QuadPart / 1000.);
+ }
+ return -1;
+#else
+ struct timespec time;
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ return ((int64_t)time.tv_sec * (int64_t)1000) + (int64_t)time.tv_nsec / (int64_t)1000;
+#endif
+}
+
+template <class T>
+inline T GetTimeSec()
+{
+ return (T)GetTimeMs() / (T)1000.0;
+}
+
+void USleep(int64_t usecs, volatile bool* stop = NULL);
--- /dev/null
+bin_PROGRAMS = cec-client
+cec_client_SOURCES = main.cpp
+cec_client_LDFLAGS = -L../lib -lcec
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "../../include/CECExports.h"
+#include "../lib/util/threads.h"
+#include "../lib/util/misc.h"
+#include "../lib/util/StdString.h"
+#include <cstdio>
+#include <fcntl.h>
+#include <iostream>
+#include <string>
+
+using namespace CEC;
+using namespace std;
+
+#define CEC_TEST_CLIENT_VERSION 1
+
+void flush_log(ICECDevice *cecParser)
+{
+ cec_log_message message;
+ while (cecParser && cecParser->GetNextLogMessage(&message))
+ {
+ switch (message.level)
+ {
+ case CEC_LOG_ERROR:
+ cout << "ERROR: " << message.message.c_str() << endl;
+ break;
+ case CEC_LOG_WARNING:
+ cout << "WARNING: " << message.message.c_str() << endl;
+ break;
+ case CEC_LOG_NOTICE:
+ cout << "NOTICE: " << message.message.c_str() << endl;
+ break;
+ case CEC_LOG_DEBUG:
+ cout << "DEBUG: " << message.message.c_str() << endl;
+ break;
+ }
+ }
+}
+
+void list_devices(ICECDevice *parser)
+{
+ cout << "Found devices: ";
+ vector<cec_device> devices;
+ int iDevicesFound = parser->FindDevices(devices);
+ if (iDevicesFound <= 0)
+ {
+#ifdef __WINDOWS__
+ cout << "Not supported yet, sorry!" << endl;
+#else
+ cout << "NONE" << endl;
+#endif
+ }
+ else
+ {
+ cout << devices.size() << endl;
+ for (unsigned int iDevicePtr = 0; iDevicePtr < devices.size(); iDevicePtr++)
+ {
+ CStdString strDevice;
+ strDevice.Format("device: %d\npath: %s\ncom port: %s", iDevicePtr, devices[iDevicePtr].path.c_str(), devices[0].comm.c_str());
+ cout << endl << strDevice.c_str() << endl;
+ }
+ }
+}
+
+void show_help(const char* strExec)
+{
+ cout << endl <<
+ strExec << " {-h|--help|-l|--list-devices|[COM PORT]}" << endl <<
+ endl <<
+ "parameters:" << endl <<
+ "\t-h --help Shows this help text" << endl <<
+ "\t-l --list-devices List all devices on this system" << endl <<
+ "\t[COM PORT] The com port to connect to. If no COM port is given, the client tries to connect to the first device that is detected" << endl;
+}
+
+int main (int argc, char *argv[])
+{
+ ICECDevice *parser = LoadLibCec("CEC Test Client");
+ if (!parser && parser->GetMinVersion() > CEC_TEST_CLIENT_VERSION)
+ {
+ cout << "Unable to create parser. Is libcec.dll present?" << endl;
+ return 1;
+ }
+ CStdString strLog;
+ strLog.Format("CEC Parser created - libcec version %d", parser->GetLibVersion());
+ cout << strLog.c_str() << endl;
+
+ //make stdin non-blocking
+#ifndef __WINDOWS__
+ int flags = fcntl(0, F_GETFL, 0);
+ flags |= O_NONBLOCK;
+ fcntl(0, F_SETFL, flags);
+#endif
+
+ string strPort;
+ if (argc < 2)
+ {
+ cout << "no serial port given. trying autodetect: ";
+ vector<cec_device> devices;
+ int iDevicesFound = parser->FindDevices(devices);
+ if (iDevicesFound <= 0)
+ {
+ cout << "FAILED" << endl;
+ UnloadLibCec(parser);
+ return 1;
+ }
+ else
+ {
+ cout << endl << " path: " << devices[0].path << endl <<
+ " com port: " << devices[0].comm << endl << endl;
+ strPort = devices[0].comm;
+ }
+ }
+ else if (!strcmp(argv[1], "--list-devices") || !strcmp(argv[1], "-l"))
+ {
+ list_devices(parser);
+ UnloadLibCec(parser);
+ return 0;
+ }
+ else if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))
+ {
+ show_help(argv[0]);
+ return 0;
+ }
+ else
+ {
+ strPort = argv[1];
+ }
+
+ if (!parser->Open(strPort.c_str()))
+ {
+ cout << "unable to open the device on port " << strPort << endl;
+ flush_log(parser);
+ UnloadLibCec(parser);
+ return 1;
+ }
+
+ cout << "cec device opened" << endl;
+ usleep(CEC_SETTLE_DOWN_TIME);
+
+ parser->PowerOnDevices();
+ flush_log(parser);
+
+ parser->SetActiveView();
+ flush_log(parser);
+
+ bool bContinue(true);
+ cout << "waiting for input" << endl;
+ while (bContinue)
+ {
+ flush_log(parser);
+
+ string input;
+ getline(cin, input);
+ cin.clear();
+
+ if (!input.empty())
+ {
+ string command;
+ if (GetWord(input, command))
+ {
+ if (command == "tx")
+ {
+ string strvalue;
+ int ivalue;
+ vector<uint8_t> bytes;
+ while (GetWord(input, strvalue) && HexStrToInt(strvalue, ivalue))
+ bytes.push_back(ivalue);
+
+ parser->Transmit(bytes);
+ }
+ else if (command == "am")
+ {
+ string strvalue;
+ int ackmask;
+ vector<uint8_t> bytes;
+ if (GetWord(input, strvalue) && HexStrToInt(strvalue, ackmask))
+ {
+ parser->SetAckMask((cec_logical_address) ackmask);
+ }
+ }
+ else if (command == "ping")
+ {
+ parser->Ping();
+ }
+ else if (command == "bl")
+ {
+ parser->StartBootloader();
+ }
+ else if (command == "q" || command == "quit")
+ {
+ bContinue = false;
+ }
+ }
+ if (bContinue)
+ cout << "waiting for input" << endl;
+ }
+ CCondition::Sleep(50);
+ }
+
+ parser->PowerOffDevices();
+ flush_log(parser);
+ UnloadLibCec(parser);
+ return 0;
+}