initial commit containing libcec v0.1. see README for details.
authorLars Op den Kamp <lars@opdenkamp.eu>
Wed, 28 Sep 2011 22:52:53 +0000 (00:52 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Wed, 28 Sep 2011 22:53:52 +0000 (00:53 +0200)
58 files changed:
.gitignore [new file with mode: 0644]
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
configure.ac [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/rules [new file with mode: 0755]
include/CECExports.h [new file with mode: 0644]
include/CECExportsC.h [new file with mode: 0644]
include/CECExportsCpp.h [new file with mode: 0644]
include/CECTypes.h [new file with mode: 0644]
project/libcec.filters [new file with mode: 0644]
project/libcec.sln [new file with mode: 0644]
project/libcec.vcxproj [new file with mode: 0644]
project/libcec.vcxproj.filters [new file with mode: 0644]
project/testclient.vcxproj [new file with mode: 0644]
project/testclient.vcxproj.filters [new file with mode: 0644]
pthreadVC2.dll [new file with mode: 0644]
pthreadVC2d.dll [new file with mode: 0644]
src/lib/CECDetect.cpp [new file with mode: 0644]
src/lib/CECDetect.h [new file with mode: 0644]
src/lib/CECDll.cpp [new file with mode: 0644]
src/lib/CECParser.cpp [new file with mode: 0644]
src/lib/CECParser.h [new file with mode: 0644]
src/lib/CECParserC.cpp [new file with mode: 0644]
src/lib/Makefile.am [new file with mode: 0644]
src/lib/libPlatform/baudrate.h [new file with mode: 0644]
src/lib/libPlatform/linux/os_posix.h [new file with mode: 0644]
src/lib/libPlatform/linux/serialport.cpp [new file with mode: 0644]
src/lib/libPlatform/os-dependent.h [new file with mode: 0644]
src/lib/libPlatform/pthread_win32/pthread.h [new file with mode: 0644]
src/lib/libPlatform/pthread_win32/pthreadVC2.lib [new file with mode: 0644]
src/lib/libPlatform/pthread_win32/pthreadVC2d.lib [new file with mode: 0644]
src/lib/libPlatform/pthread_win32/sched.h [new file with mode: 0644]
src/lib/libPlatform/pthread_win32/semaphore.h [new file with mode: 0644]
src/lib/libPlatform/serialport.h [new file with mode: 0644]
src/lib/libPlatform/windows/dlfcn-win32.cpp [new file with mode: 0644]
src/lib/libPlatform/windows/dlfcn-win32.h [new file with mode: 0644]
src/lib/libPlatform/windows/os_windows.cpp [new file with mode: 0644]
src/lib/libPlatform/windows/os_windows.h [new file with mode: 0644]
src/lib/libPlatform/windows/serialport.cpp [new file with mode: 0644]
src/lib/libcec.pc.in [new file with mode: 0644]
src/lib/util/StdString.h [new file with mode: 0644]
src/lib/util/buffer.h [new file with mode: 0644]
src/lib/util/misc.cpp [new file with mode: 0644]
src/lib/util/misc.h [new file with mode: 0644]
src/lib/util/threads.cpp [new file with mode: 0644]
src/lib/util/threads.h [new file with mode: 0644]
src/lib/util/timeutils.h [new file with mode: 0644]
src/testclient/Makefile.am [new file with mode: 0644]
src/testclient/main.cpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b6443c1
--- /dev/null
@@ -0,0 +1,56 @@
+.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
+
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..b04e44e
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+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
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..0d91a1e
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,706 @@
+/*
+ * 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>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..877a982
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,5 @@
+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
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..c68f68b
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src/lib src/testclient
\ No newline at end of file
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..b8b2f7d
--- /dev/null
+++ b/README
@@ -0,0 +1,16 @@
+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
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..45b0e49
--- /dev/null
@@ -0,0 +1,12 @@
+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
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..d54ce14
--- /dev/null
@@ -0,0 +1,5 @@
+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
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7f8f011
--- /dev/null
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..1041755
--- /dev/null
@@ -0,0 +1,14 @@
+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.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..0d91a1e
--- /dev/null
@@ -0,0 +1,706 @@
+/*
+ * 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>.
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..dfa93e8
--- /dev/null
@@ -0,0 +1,4 @@
+README
+COPYING
+AUTHORS
+ChangeLog
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..3d3d89c
--- /dev/null
@@ -0,0 +1,13 @@
+#!/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  $@
diff --git a/include/CECExports.h b/include/CECExports.h
new file mode 100644 (file)
index 0000000..3a72aea
--- /dev/null
@@ -0,0 +1,205 @@
+#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_ */
diff --git a/include/CECExportsC.h b/include/CECExportsC.h
new file mode 100644 (file)
index 0000000..04ce11a
--- /dev/null
@@ -0,0 +1,169 @@
+#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_ */
diff --git a/include/CECExportsCpp.h b/include/CECExportsCpp.h
new file mode 100644 (file)
index 0000000..195ddf5
--- /dev/null
@@ -0,0 +1,149 @@
+#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
diff --git a/include/CECTypes.h b/include/CECTypes.h
new file mode 100644 (file)
index 0000000..dcc4c72
--- /dev/null
@@ -0,0 +1,434 @@
+#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
diff --git a/project/libcec.filters b/project/libcec.filters
new file mode 100644 (file)
index 0000000..efb6144
--- /dev/null
@@ -0,0 +1,63 @@
+<?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
diff --git a/project/libcec.sln b/project/libcec.sln
new file mode 100644 (file)
index 0000000..2284eec
--- /dev/null
@@ -0,0 +1,24 @@
+
+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
diff --git a/project/libcec.vcxproj b/project/libcec.vcxproj
new file mode 100644 (file)
index 0000000..460586f
--- /dev/null
@@ -0,0 +1,133 @@
+<?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
diff --git a/project/libcec.vcxproj.filters b/project/libcec.vcxproj.filters
new file mode 100644 (file)
index 0000000..f9f44b3
--- /dev/null
@@ -0,0 +1,98 @@
+<?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
diff --git a/project/testclient.vcxproj b/project/testclient.vcxproj
new file mode 100644 (file)
index 0000000..caa2a03
--- /dev/null
@@ -0,0 +1,104 @@
+<?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
diff --git a/project/testclient.vcxproj.filters b/project/testclient.vcxproj.filters
new file mode 100644 (file)
index 0000000..a6fda36
--- /dev/null
@@ -0,0 +1,65 @@
+<?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
diff --git a/pthreadVC2.dll b/pthreadVC2.dll
new file mode 100644 (file)
index 0000000..fdea676
Binary files /dev/null and b/pthreadVC2.dll differ
diff --git a/pthreadVC2d.dll b/pthreadVC2d.dll
new file mode 100644 (file)
index 0000000..6fffdc4
Binary files /dev/null and b/pthreadVC2d.dll differ
diff --git a/src/lib/CECDetect.cpp b/src/lib/CECDetect.cpp
new file mode 100644 (file)
index 0000000..2a2668b
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * 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;
+}
diff --git a/src/lib/CECDetect.h b/src/lib/CECDetect.h
new file mode 100644 (file)
index 0000000..b3cb7e0
--- /dev/null
@@ -0,0 +1,43 @@
+#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);
+  };
+};
diff --git a/src/lib/CECDll.cpp b/src/lib/CECDll.cpp
new file mode 100644 (file)
index 0000000..ad90164
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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;
+}
+
diff --git a/src/lib/CECParser.cpp b/src/lib/CECParser.cpp
new file mode 100644 (file)
index 0000000..52b2711
--- /dev/null
@@ -0,0 +1,876 @@
+/*
+ * 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));
+}
diff --git a/src/lib/CECParser.h b/src/lib/CECParser.h
new file mode 100644 (file)
index 0000000..3ad6cf0
--- /dev/null
@@ -0,0 +1,117 @@
+#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;
+  };
+};
diff --git a/src/lib/CECParserC.cpp b/src/lib/CECParserC.cpp
new file mode 100644 (file)
index 0000000..84d5410
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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;
+}
+
+//@}
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644 (file)
index 0000000..ca89d5a
--- /dev/null
@@ -0,0 +1,31 @@
+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@
diff --git a/src/lib/libPlatform/baudrate.h b/src/lib/libPlatform/baudrate.h
new file mode 100644 (file)
index 0000000..39a4b1a
--- /dev/null
@@ -0,0 +1,179 @@
+#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}
+};
diff --git a/src/lib/libPlatform/linux/os_posix.h b/src/lib/libPlatform/linux/os_posix.h
new file mode 100644 (file)
index 0000000..1ea8aa5
--- /dev/null
@@ -0,0 +1,60 @@
+#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);
+}
diff --git a/src/lib/libPlatform/linux/serialport.cpp b/src/lib/libPlatform/linux/serialport.cpp
new file mode 100644 (file)
index 0000000..33a7385
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * 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;
+}
diff --git a/src/lib/libPlatform/os-dependent.h b/src/lib/libPlatform/os-dependent.h
new file mode 100644 (file)
index 0000000..3ea7cb4
--- /dev/null
@@ -0,0 +1,39 @@
+#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
diff --git a/src/lib/libPlatform/pthread_win32/pthread.h b/src/lib/libPlatform/pthread_win32/pthread.h
new file mode 100644 (file)
index 0000000..a3140e1
--- /dev/null
@@ -0,0 +1,1368 @@
+/* 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 */
diff --git a/src/lib/libPlatform/pthread_win32/pthreadVC2.lib b/src/lib/libPlatform/pthread_win32/pthreadVC2.lib
new file mode 100644 (file)
index 0000000..bc36770
Binary files /dev/null and b/src/lib/libPlatform/pthread_win32/pthreadVC2.lib differ
diff --git a/src/lib/libPlatform/pthread_win32/pthreadVC2d.lib b/src/lib/libPlatform/pthread_win32/pthreadVC2d.lib
new file mode 100644 (file)
index 0000000..0df71c7
Binary files /dev/null and b/src/lib/libPlatform/pthread_win32/pthreadVC2d.lib differ
diff --git a/src/lib/libPlatform/pthread_win32/sched.h b/src/lib/libPlatform/pthread_win32/sched.h
new file mode 100644 (file)
index 0000000..dfb8e93
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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 */
+
diff --git a/src/lib/libPlatform/pthread_win32/semaphore.h b/src/lib/libPlatform/pthread_win32/semaphore.h
new file mode 100644 (file)
index 0000000..a3330a6
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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 */
diff --git a/src/lib/libPlatform/serialport.h b/src/lib/libPlatform/serialport.h
new file mode 100644 (file)
index 0000000..f592ee3
--- /dev/null
@@ -0,0 +1,107 @@
+#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
+};
diff --git a/src/lib/libPlatform/windows/dlfcn-win32.cpp b/src/lib/libPlatform/windows/dlfcn-win32.cpp
new file mode 100644 (file)
index 0000000..5839921
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * 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;
+}
+
diff --git a/src/lib/libPlatform/windows/dlfcn-win32.h b/src/lib/libPlatform/windows/dlfcn-win32.h
new file mode 100644 (file)
index 0000000..b93a029
--- /dev/null
@@ -0,0 +1,46 @@
+#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 */
diff --git a/src/lib/libPlatform/windows/os_windows.cpp b/src/lib/libPlatform/windows/os_windows.cpp
new file mode 100644 (file)
index 0000000..429730d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *      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(&current);
+
+  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;
+}
diff --git a/src/lib/libPlatform/windows/os_windows.h b/src/lib/libPlatform/windows/os_windows.h
new file mode 100644 (file)
index 0000000..ae17d63
--- /dev/null
@@ -0,0 +1,74 @@
+#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);
diff --git a/src/lib/libPlatform/windows/serialport.cpp b/src/lib/libPlatform/windows/serialport.cpp
new file mode 100644 (file)
index 0000000..f4b8c62
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * 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;
+}
diff --git a/src/lib/libcec.pc.in b/src/lib/libcec.pc.in
new file mode 100644 (file)
index 0000000..058a9de
--- /dev/null
@@ -0,0 +1,12 @@
+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}
diff --git a/src/lib/util/StdString.h b/src/lib/util/StdString.h
new file mode 100644 (file)
index 0000000..9800f94
--- /dev/null
@@ -0,0 +1,4336 @@
+#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
diff --git a/src/lib/util/buffer.h b/src/lib/util/buffer.h
new file mode 100644 (file)
index 0000000..299b019
--- /dev/null
@@ -0,0 +1,66 @@
+#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;
+  };
diff --git a/src/lib/util/misc.cpp b/src/lib/util/misc.cpp
new file mode 100644 (file)
index 0000000..3cf71bd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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);
+  }
+}
diff --git a/src/lib/util/misc.h b/src/lib/util/misc.h
new file mode 100644 (file)
index 0000000..e3ff857
--- /dev/null
@@ -0,0 +1,177 @@
+#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;
+}
diff --git a/src/lib/util/threads.cpp b/src/lib/util/threads.cpp
new file mode 100644 (file)
index 0000000..3bfc1bd
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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);
+}
diff --git a/src/lib/util/threads.h b/src/lib/util/threads.h
new file mode 100644 (file)
index 0000000..41ad2b5
--- /dev/null
@@ -0,0 +1,80 @@
+#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;
+};
diff --git a/src/lib/util/timeutils.h b/src/lib/util/timeutils.h
new file mode 100644 (file)
index 0000000..f1c0e63
--- /dev/null
@@ -0,0 +1,52 @@
+#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);
diff --git a/src/testclient/Makefile.am b/src/testclient/Makefile.am
new file mode 100644 (file)
index 0000000..33d9a07
--- /dev/null
@@ -0,0 +1,3 @@
+bin_PROGRAMS = cec-client
+cec_client_SOURCES = main.cpp
+cec_client_LDFLAGS = -L../lib -lcec
diff --git a/src/testclient/main.cpp b/src/testclient/main.cpp
new file mode 100644 (file)
index 0000000..1aa790b
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * 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;
+}