Merge libguac-client-rdp.
This commit is contained in:
commit
aaf8a0829d
36
protocols/rdp/.gitignore
vendored
Normal file
36
protocols/rdp/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
# Object code
|
||||
*.o
|
||||
*.so
|
||||
*.lo
|
||||
*.la
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
# Release files
|
||||
*.tar.gz
|
||||
|
||||
# Files currently being edited by vim or vi
|
||||
*.swp
|
||||
|
||||
# automake/autoconf
|
||||
.deps/
|
||||
.libs/
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
m4/*
|
||||
!README
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
|
6
protocols/rdp/AUTHORS
Normal file
6
protocols/rdp/AUTHORS
Normal file
@ -0,0 +1,6 @@
|
||||
Michael Jumper <mike.jumper@guac-dev.org>
|
||||
Matt Hortman <matt@FlintRiverSystems.com>
|
||||
Jocelyn Delalande <j.delalande@ulteo.com>
|
||||
David Lechevalier <david@ulteo.com>
|
||||
Alexandre Devely <alex@koumoula.com>
|
||||
Laurent Meunier <laurent@deltalima.net>
|
49
protocols/rdp/ChangeLog
Normal file
49
protocols/rdp/ChangeLog
Normal file
@ -0,0 +1,49 @@
|
||||
2013-05-09 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Merge contributed keymaps for French and German.
|
||||
|
||||
2012-12-25 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Console arguments (fixes #227)
|
||||
|
||||
2012-12-13 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Implement PATBLT fallback (fixes #238)
|
||||
|
||||
2012-11-22 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Add disable-audio option (fixes #221)
|
||||
|
||||
2012-11-02 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Added sound support (fixes #32)
|
||||
|
||||
2012-10-22 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Use guac_client_info to choose optimal size if size not overridden
|
||||
|
||||
2012-08-31 Laurent Meunier <laurent@deltalima.net>
|
||||
|
||||
* Use configured color depth
|
||||
|
||||
2012-08-11 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Fix m4/ autoreconf error
|
||||
|
||||
2012-05-23 David Pham-Van <d.pham-van@ulteo.com>
|
||||
|
||||
* Add SetNull and SetDefault handlers (fixes #148)
|
||||
|
||||
2012-05-04 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Removed Alt-code fallback mode
|
||||
* Added embedded default mouse pointer
|
||||
|
||||
2012-05-15 Jocelyn Delalande <j.delalande@ulteo.com>
|
||||
|
||||
* Unicode keyboard events
|
||||
|
||||
2012-05-04 Michael Jumper <mike.jumper@guac-dev.org>
|
||||
|
||||
* Initial release
|
||||
|
470
protocols/rdp/LICENSE
Normal file
470
protocols/rdp/LICENSE
Normal file
@ -0,0 +1,470 @@
|
||||
MOZILLA PUBLIC LICENSE
|
||||
Version 1.1
|
||||
|
||||
---------------
|
||||
|
||||
1. Definitions.
|
||||
|
||||
1.0.1. "Commercial Use" means distribution or otherwise making the
|
||||
Covered Code available to a third party.
|
||||
|
||||
1.1. "Contributor" means each entity that creates or contributes to
|
||||
the creation of Modifications.
|
||||
|
||||
1.2. "Contributor Version" means the combination of the Original
|
||||
Code, prior Modifications used by a Contributor, and the Modifications
|
||||
made by that particular Contributor.
|
||||
|
||||
1.3. "Covered Code" means the Original Code or Modifications or the
|
||||
combination of the Original Code and Modifications, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.4. "Electronic Distribution Mechanism" means a mechanism generally
|
||||
accepted in the software development community for the electronic
|
||||
transfer of data.
|
||||
|
||||
1.5. "Executable" means Covered Code in any form other than Source
|
||||
Code.
|
||||
|
||||
1.6. "Initial Developer" means the individual or entity identified
|
||||
as the Initial Developer in the Source Code notice required by Exhibit
|
||||
A.
|
||||
|
||||
1.7. "Larger Work" means a work which combines Covered Code or
|
||||
portions thereof with code not governed by the terms of this License.
|
||||
|
||||
1.8. "License" means this document.
|
||||
|
||||
1.8.1. "Licensable" means having the right to grant, to the maximum
|
||||
extent possible, whether at the time of the initial grant or
|
||||
subsequently acquired, any and all of the rights conveyed herein.
|
||||
|
||||
1.9. "Modifications" means any addition to or deletion from the
|
||||
substance or structure of either the Original Code or any previous
|
||||
Modifications. When Covered Code is released as a series of files, a
|
||||
Modification is:
|
||||
A. Any addition to or deletion from the contents of a file
|
||||
containing Original Code or previous Modifications.
|
||||
|
||||
B. Any new file that contains any part of the Original Code or
|
||||
previous Modifications.
|
||||
|
||||
1.10. "Original Code" means Source Code of computer software code
|
||||
which is described in the Source Code notice required by Exhibit A as
|
||||
Original Code, and which, at the time of its release under this
|
||||
License is not already Covered Code governed by this License.
|
||||
|
||||
1.10.1. "Patent Claims" means any patent claim(s), now owned or
|
||||
hereafter acquired, including without limitation, method, process,
|
||||
and apparatus claims, in any patent Licensable by grantor.
|
||||
|
||||
1.11. "Source Code" means the preferred form of the Covered Code for
|
||||
making modifications to it, including all modules it contains, plus
|
||||
any associated interface definition files, scripts used to control
|
||||
compilation and installation of an Executable, or source code
|
||||
differential comparisons against either the Original Code or another
|
||||
well known, available Covered Code of the Contributor's choice. The
|
||||
Source Code can be in a compressed or archival form, provided the
|
||||
appropriate decompression or de-archiving software is widely available
|
||||
for no charge.
|
||||
|
||||
1.12. "You" (or "Your") means an individual or a legal entity
|
||||
exercising rights under, and complying with all of the terms of, this
|
||||
License or a future version of this License issued under Section 6.1.
|
||||
For legal entities, "You" includes any entity which controls, is
|
||||
controlled by, or is under common control with You. For purposes of
|
||||
this definition, "control" means (a) the power, direct or indirect,
|
||||
to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (b) ownership of more than fifty percent
|
||||
(50%) of the outstanding shares or beneficial ownership of such
|
||||
entity.
|
||||
|
||||
2. Source Code License.
|
||||
|
||||
2.1. The Initial Developer Grant.
|
||||
The Initial Developer hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license, subject to third party intellectual property
|
||||
claims:
|
||||
(a) under intellectual property rights (other than patent or
|
||||
trademark) Licensable by Initial Developer to use, reproduce,
|
||||
modify, display, perform, sublicense and distribute the Original
|
||||
Code (or portions thereof) with or without Modifications, and/or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patents Claims infringed by the making, using or
|
||||
selling of Original Code, to make, have made, use, practice,
|
||||
sell, and offer for sale, and/or otherwise dispose of the
|
||||
Original Code (or portions thereof).
|
||||
|
||||
(c) the licenses granted in this Section 2.1(a) and (b) are
|
||||
effective on the date Initial Developer first distributes
|
||||
Original Code under the terms of this License.
|
||||
|
||||
(d) Notwithstanding Section 2.1(b) above, no patent license is
|
||||
granted: 1) for code that You delete from the Original Code; 2)
|
||||
separate from the Original Code; or 3) for infringements caused
|
||||
by: i) the modification of the Original Code or ii) the
|
||||
combination of the Original Code with other software or devices.
|
||||
|
||||
2.2. Contributor Grant.
|
||||
Subject to third party intellectual property claims, each Contributor
|
||||
hereby grants You a world-wide, royalty-free, non-exclusive license
|
||||
|
||||
(a) under intellectual property rights (other than patent or
|
||||
trademark) Licensable by Contributor, to use, reproduce, modify,
|
||||
display, perform, sublicense and distribute the Modifications
|
||||
created by such Contributor (or portions thereof) either on an
|
||||
unmodified basis, with other Modifications, as Covered Code
|
||||
and/or as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims infringed by the making, using, or
|
||||
selling of Modifications made by that Contributor either alone
|
||||
and/or in combination with its Contributor Version (or portions
|
||||
of such combination), to make, use, sell, offer for sale, have
|
||||
made, and/or otherwise dispose of: 1) Modifications made by that
|
||||
Contributor (or portions thereof); and 2) the combination of
|
||||
Modifications made by that Contributor with its Contributor
|
||||
Version (or portions of such combination).
|
||||
|
||||
(c) the licenses granted in Sections 2.2(a) and 2.2(b) are
|
||||
effective on the date Contributor first makes Commercial Use of
|
||||
the Covered Code.
|
||||
|
||||
(d) Notwithstanding Section 2.2(b) above, no patent license is
|
||||
granted: 1) for any code that Contributor has deleted from the
|
||||
Contributor Version; 2) separate from the Contributor Version;
|
||||
3) for infringements caused by: i) third party modifications of
|
||||
Contributor Version or ii) the combination of Modifications made
|
||||
by that Contributor with other software (except as part of the
|
||||
Contributor Version) or other devices; or 4) under Patent Claims
|
||||
infringed by Covered Code in the absence of Modifications made by
|
||||
that Contributor.
|
||||
|
||||
3. Distribution Obligations.
|
||||
|
||||
3.1. Application of License.
|
||||
The Modifications which You create or to which You contribute are
|
||||
governed by the terms of this License, including without limitation
|
||||
Section 2.2. The Source Code version of Covered Code may be
|
||||
distributed only under the terms of this License or a future version
|
||||
of this License released under Section 6.1, and You must include a
|
||||
copy of this License with every copy of the Source Code You
|
||||
distribute. You may not offer or impose any terms on any Source Code
|
||||
version that alters or restricts the applicable version of this
|
||||
License or the recipients' rights hereunder. However, You may include
|
||||
an additional document offering the additional rights described in
|
||||
Section 3.5.
|
||||
|
||||
3.2. Availability of Source Code.
|
||||
Any Modification which You create or to which You contribute must be
|
||||
made available in Source Code form under the terms of this License
|
||||
either on the same media as an Executable version or via an accepted
|
||||
Electronic Distribution Mechanism to anyone to whom you made an
|
||||
Executable version available; and if made available via Electronic
|
||||
Distribution Mechanism, must remain available for at least twelve (12)
|
||||
months after the date it initially became available, or at least six
|
||||
(6) months after a subsequent version of that particular Modification
|
||||
has been made available to such recipients. You are responsible for
|
||||
ensuring that the Source Code version remains available even if the
|
||||
Electronic Distribution Mechanism is maintained by a third party.
|
||||
|
||||
3.3. Description of Modifications.
|
||||
You must cause all Covered Code to which You contribute to contain a
|
||||
file documenting the changes You made to create that Covered Code and
|
||||
the date of any change. You must include a prominent statement that
|
||||
the Modification is derived, directly or indirectly, from Original
|
||||
Code provided by the Initial Developer and including the name of the
|
||||
Initial Developer in (a) the Source Code, and (b) in any notice in an
|
||||
Executable version or related documentation in which You describe the
|
||||
origin or ownership of the Covered Code.
|
||||
|
||||
3.4. Intellectual Property Matters
|
||||
(a) Third Party Claims.
|
||||
If Contributor has knowledge that a license under a third party's
|
||||
intellectual property rights is required to exercise the rights
|
||||
granted by such Contributor under Sections 2.1 or 2.2,
|
||||
Contributor must include a text file with the Source Code
|
||||
distribution titled "LEGAL" which describes the claim and the
|
||||
party making the claim in sufficient detail that a recipient will
|
||||
know whom to contact. If Contributor obtains such knowledge after
|
||||
the Modification is made available as described in Section 3.2,
|
||||
Contributor shall promptly modify the LEGAL file in all copies
|
||||
Contributor makes available thereafter and shall take other steps
|
||||
(such as notifying appropriate mailing lists or newsgroups)
|
||||
reasonably calculated to inform those who received the Covered
|
||||
Code that new knowledge has been obtained.
|
||||
|
||||
(b) Contributor APIs.
|
||||
If Contributor's Modifications include an application programming
|
||||
interface and Contributor has knowledge of patent licenses which
|
||||
are reasonably necessary to implement that API, Contributor must
|
||||
also include this information in the LEGAL file.
|
||||
|
||||
(c) Representations.
|
||||
Contributor represents that, except as disclosed pursuant to
|
||||
Section 3.4(a) above, Contributor believes that Contributor's
|
||||
Modifications are Contributor's original creation(s) and/or
|
||||
Contributor has sufficient rights to grant the rights conveyed by
|
||||
this License.
|
||||
|
||||
3.5. Required Notices.
|
||||
You must duplicate the notice in Exhibit A in each file of the Source
|
||||
Code. If it is not possible to put such notice in a particular Source
|
||||
Code file due to its structure, then You must include such notice in a
|
||||
location (such as a relevant directory) where a user would be likely
|
||||
to look for such a notice. If You created one or more Modification(s)
|
||||
You may add your name as a Contributor to the notice described in
|
||||
Exhibit A. You must also duplicate this License in any documentation
|
||||
for the Source Code where You describe recipients' rights or ownership
|
||||
rights relating to Covered Code. You may choose to offer, and to
|
||||
charge a fee for, warranty, support, indemnity or liability
|
||||
obligations to one or more recipients of Covered Code. However, You
|
||||
may do so only on Your own behalf, and not on behalf of the Initial
|
||||
Developer or any Contributor. You must make it absolutely clear than
|
||||
any such warranty, support, indemnity or liability obligation is
|
||||
offered by You alone, and You hereby agree to indemnify the Initial
|
||||
Developer and every Contributor for any liability incurred by the
|
||||
Initial Developer or such Contributor as a result of warranty,
|
||||
support, indemnity or liability terms You offer.
|
||||
|
||||
3.6. Distribution of Executable Versions.
|
||||
You may distribute Covered Code in Executable form only if the
|
||||
requirements of Section 3.1-3.5 have been met for that Covered Code,
|
||||
and if You include a notice stating that the Source Code version of
|
||||
the Covered Code is available under the terms of this License,
|
||||
including a description of how and where You have fulfilled the
|
||||
obligations of Section 3.2. The notice must be conspicuously included
|
||||
in any notice in an Executable version, related documentation or
|
||||
collateral in which You describe recipients' rights relating to the
|
||||
Covered Code. You may distribute the Executable version of Covered
|
||||
Code or ownership rights under a license of Your choice, which may
|
||||
contain terms different from this License, provided that You are in
|
||||
compliance with the terms of this License and that the license for the
|
||||
Executable version does not attempt to limit or alter the recipient's
|
||||
rights in the Source Code version from the rights set forth in this
|
||||
License. If You distribute the Executable version under a different
|
||||
license You must make it absolutely clear that any terms which differ
|
||||
from this License are offered by You alone, not by the Initial
|
||||
Developer or any Contributor. You hereby agree to indemnify the
|
||||
Initial Developer and every Contributor for any liability incurred by
|
||||
the Initial Developer or such Contributor as a result of any such
|
||||
terms You offer.
|
||||
|
||||
3.7. Larger Works.
|
||||
You may create a Larger Work by combining Covered Code with other code
|
||||
not governed by the terms of this License and distribute the Larger
|
||||
Work as a single product. In such a case, You must make sure the
|
||||
requirements of this License are fulfilled for the Covered Code.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation.
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Code due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description
|
||||
must be included in the LEGAL file described in Section 3.4 and must
|
||||
be included with all distributions of the Source Code. Except to the
|
||||
extent prohibited by statute or regulation, such description must be
|
||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||
understand it.
|
||||
|
||||
5. Application of this License.
|
||||
|
||||
This License applies to code to which the Initial Developer has
|
||||
attached the notice in Exhibit A and to related Covered Code.
|
||||
|
||||
6. Versions of the License.
|
||||
|
||||
6.1. New Versions.
|
||||
Netscape Communications Corporation ("Netscape") may publish revised
|
||||
and/or new versions of the License from time to time. Each version
|
||||
will be given a distinguishing version number.
|
||||
|
||||
6.2. Effect of New Versions.
|
||||
Once Covered Code has been published under a particular version of the
|
||||
License, You may always continue to use it under the terms of that
|
||||
version. You may also choose to use such Covered Code under the terms
|
||||
of any subsequent version of the License published by Netscape. No one
|
||||
other than Netscape has the right to modify the terms applicable to
|
||||
Covered Code created under this License.
|
||||
|
||||
6.3. Derivative Works.
|
||||
If You create or use a modified version of this License (which you may
|
||||
only do in order to apply it to code which is not already Covered Code
|
||||
governed by this License), You must (a) rename Your license so that
|
||||
the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
|
||||
"MPL", "NPL" or any confusingly similar phrase do not appear in your
|
||||
license (except to note that your license differs from this License)
|
||||
and (b) otherwise make it clear that Your version of the license
|
||||
contains terms which differ from the Mozilla Public License and
|
||||
Netscape Public License. (Filling in the name of the Initial
|
||||
Developer, Original Code or Contributor in the notice described in
|
||||
Exhibit A shall not of themselves be deemed to be modifications of
|
||||
this License.)
|
||||
|
||||
7. DISCLAIMER OF WARRANTY.
|
||||
|
||||
COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
|
||||
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
|
||||
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
|
||||
IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
|
||||
YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
|
||||
COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
|
||||
OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
|
||||
ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
|
||||
|
||||
8. TERMINATION.
|
||||
|
||||
8.1. This License and the rights granted hereunder will terminate
|
||||
automatically if You fail to comply with terms herein and fail to cure
|
||||
such breach within 30 days of becoming aware of the breach. All
|
||||
sublicenses to the Covered Code which are properly granted shall
|
||||
survive any termination of this License. Provisions which, by their
|
||||
nature, must remain in effect beyond the termination of this License
|
||||
shall survive.
|
||||
|
||||
8.2. If You initiate litigation by asserting a patent infringement
|
||||
claim (excluding declatory judgment actions) against Initial Developer
|
||||
or a Contributor (the Initial Developer or Contributor against whom
|
||||
You file such action is referred to as "Participant") alleging that:
|
||||
|
||||
(a) such Participant's Contributor Version directly or indirectly
|
||||
infringes any patent, then any and all rights granted by such
|
||||
Participant to You under Sections 2.1 and/or 2.2 of this License
|
||||
shall, upon 60 days notice from Participant terminate prospectively,
|
||||
unless if within 60 days after receipt of notice You either: (i)
|
||||
agree in writing to pay Participant a mutually agreeable reasonable
|
||||
royalty for Your past and future use of Modifications made by such
|
||||
Participant, or (ii) withdraw Your litigation claim with respect to
|
||||
the Contributor Version against such Participant. If within 60 days
|
||||
of notice, a reasonable royalty and payment arrangement are not
|
||||
mutually agreed upon in writing by the parties or the litigation claim
|
||||
is not withdrawn, the rights granted by Participant to You under
|
||||
Sections 2.1 and/or 2.2 automatically terminate at the expiration of
|
||||
the 60 day notice period specified above.
|
||||
|
||||
(b) any software, hardware, or device, other than such Participant's
|
||||
Contributor Version, directly or indirectly infringes any patent, then
|
||||
any rights granted to You by such Participant under Sections 2.1(b)
|
||||
and 2.2(b) are revoked effective as of the date You first made, used,
|
||||
sold, distributed, or had made, Modifications made by that
|
||||
Participant.
|
||||
|
||||
8.3. If You assert a patent infringement claim against Participant
|
||||
alleging that such Participant's Contributor Version directly or
|
||||
indirectly infringes any patent where such claim is resolved (such as
|
||||
by license or settlement) prior to the initiation of patent
|
||||
infringement litigation, then the reasonable value of the licenses
|
||||
granted by such Participant under Sections 2.1 or 2.2 shall be taken
|
||||
into account in determining the amount or value of any payment or
|
||||
license.
|
||||
|
||||
8.4. In the event of termination under Sections 8.1 or 8.2 above,
|
||||
all end user license agreements (excluding distributors and resellers)
|
||||
which have been validly granted by You or any distributor hereunder
|
||||
prior to termination shall survive termination.
|
||||
|
||||
9. LIMITATION OF LIABILITY.
|
||||
|
||||
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
|
||||
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
|
||||
DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
|
||||
OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
|
||||
ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
|
||||
CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
|
||||
WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
|
||||
COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
|
||||
INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
|
||||
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
|
||||
RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
|
||||
PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
|
||||
EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
|
||||
THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
10. U.S. GOVERNMENT END USERS.
|
||||
|
||||
The Covered Code is a "commercial item," as that term is defined in
|
||||
48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
|
||||
software" and "commercial computer software documentation," as such
|
||||
terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
|
||||
C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
|
||||
all U.S. Government End Users acquire Covered Code with only those
|
||||
rights set forth herein.
|
||||
|
||||
11. MISCELLANEOUS.
|
||||
|
||||
This License represents the complete agreement concerning subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. This License shall be governed by
|
||||
California law provisions (except to the extent applicable law, if
|
||||
any, provides otherwise), excluding its conflict-of-law provisions.
|
||||
With respect to disputes in which at least one party is a citizen of,
|
||||
or an entity chartered or registered to do business in the United
|
||||
States of America, any litigation relating to this License shall be
|
||||
subject to the jurisdiction of the Federal Courts of the Northern
|
||||
District of California, with venue lying in Santa Clara County,
|
||||
California, with the losing party responsible for costs, including
|
||||
without limitation, court costs and reasonable attorneys' fees and
|
||||
expenses. The application of the United Nations Convention on
|
||||
Contracts for the International Sale of Goods is expressly excluded.
|
||||
Any law or regulation which provides that the language of a contract
|
||||
shall be construed against the drafter shall not apply to this
|
||||
License.
|
||||
|
||||
12. RESPONSIBILITY FOR CLAIMS.
|
||||
|
||||
As between Initial Developer and the Contributors, each party is
|
||||
responsible for claims and damages arising, directly or indirectly,
|
||||
out of its utilization of rights under this License and You agree to
|
||||
work with Initial Developer and Contributors to distribute such
|
||||
responsibility on an equitable basis. Nothing herein is intended or
|
||||
shall be deemed to constitute any admission of liability.
|
||||
|
||||
13. MULTIPLE-LICENSED CODE.
|
||||
|
||||
Initial Developer may designate portions of the Covered Code as
|
||||
"Multiple-Licensed". "Multiple-Licensed" means that the Initial
|
||||
Developer permits you to utilize portions of the Covered Code under
|
||||
Your choice of the NPL or the alternative licenses, if any, specified
|
||||
by the Initial Developer in the file described in Exhibit A.
|
||||
|
||||
EXHIBIT A -Mozilla Public License.
|
||||
|
||||
``The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (the "License"); you may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is ______________________________________.
|
||||
|
||||
The Initial Developer of the Original Code is ________________________.
|
||||
Portions created by ______________________ are Copyright (C) ______
|
||||
_______________________. All Rights Reserved.
|
||||
|
||||
Contributor(s): ______________________________________.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the _____ license (the "[___] License"), in which case the
|
||||
provisions of [______] License are applicable instead of those
|
||||
above. If you wish to allow use of your version of this file only
|
||||
under the terms of the [____] License and not to allow others to use
|
||||
your version of this file under the MPL, indicate your decision by
|
||||
deleting the provisions above and replace them with the notice and
|
||||
other provisions required by the [___] License. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file
|
||||
under either the MPL or the [___] License."
|
||||
|
||||
[NOTE: The text of this Exhibit A may differ slightly from the text of
|
||||
the notices in the Source Code files of the Original Code. You should
|
||||
use the text of this Exhibit A rather than the text found in the
|
||||
Original Code Source Code for Your Modifications.]
|
||||
|
99
protocols/rdp/Makefile.am
Normal file
99
protocols/rdp/Makefile.am
Normal file
@ -0,0 +1,99 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is libguac-client-rdp.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael Jumper.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AM_CFLAGS = -Werror -Wall -Iinclude
|
||||
|
||||
lib_LTLIBRARIES = libguac-client-rdp.la
|
||||
freerdp_LTLIBRARIES = guac_rdpsnd.la
|
||||
|
||||
libguac_client_rdp_la_SOURCES = \
|
||||
$(OGG_SOURCES) \
|
||||
src/audio.c \
|
||||
src/client.c \
|
||||
src/default_pointer.c \
|
||||
src/guac_handlers.c \
|
||||
src/rdp_bitmap.c \
|
||||
src/rdp_cliprdr.c \
|
||||
src/rdp_gdi.c \
|
||||
src/rdp_glyph.c \
|
||||
src/rdp_keymap_base.c \
|
||||
src/rdp_keymap.c \
|
||||
src/rdp_keymap_de_de.c \
|
||||
src/rdp_keymap_failsafe.c \
|
||||
src/rdp_keymap_fr_fr.c \
|
||||
src/rdp_keymap_en_us.c \
|
||||
src/rdp_pointer.c \
|
||||
src/wav_encoder.c
|
||||
|
||||
guac_rdpsnd_la_SOURCES = \
|
||||
guac_rdpsnd/messages.c \
|
||||
guac_rdpsnd/service.c \
|
||||
src/audio.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
$(OGG_HEADERS) \
|
||||
guac_rdpsnd/messages.h \
|
||||
guac_rdpsnd/service.h \
|
||||
include/audio.h \
|
||||
include/client.h \
|
||||
include/config.h \
|
||||
include/default_pointer.h \
|
||||
include/guac_handlers.h \
|
||||
include/rdp_bitmap.h \
|
||||
include/rdp_cliprdr.h \
|
||||
include/rdp_gdi.h \
|
||||
include/rdp_glyph.h \
|
||||
include/rdp_keymap.h \
|
||||
include/rdp_pointer.h \
|
||||
include/wav_encoder.h
|
||||
|
||||
# Compile OGG support if available
|
||||
if ENABLE_OGG
|
||||
libguac_client_rdp_la_SOURCES += src/ogg_encoder.c
|
||||
noinst_HEADERS += include/ogg_encoder.h
|
||||
endif
|
||||
|
||||
|
||||
libguac_client_rdp_la_LDFLAGS = -version-info 0:0:0
|
||||
guac_rdpsnd_la_LDFLAGS = -module -avoid-version -shared
|
||||
|
||||
freerdpdir = ${libdir}/freerdp/
|
||||
|
||||
EXTRA_DIST = LICENSE
|
||||
|
75
protocols/rdp/README
Normal file
75
protocols/rdp/README
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
------------------------------------------------------------
|
||||
About this README
|
||||
------------------------------------------------------------
|
||||
|
||||
This README is intended to provide quick and to-the-point documentation for
|
||||
technical users intending to compile parts of Guacamole themselves.
|
||||
|
||||
Distribution-specific packages are available from the files section of the main
|
||||
project page:
|
||||
|
||||
http://sourceforge.net/projects/guacamole/files/
|
||||
|
||||
Distribution-specific documentation is provided on the Guacamole wiki:
|
||||
|
||||
http://guac-dev.org/
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
What is libguac-client-rdp?
|
||||
------------------------------------------------------------
|
||||
|
||||
libguac-client-rdp is a protocol support plugin for the Guacamole proxy (guacd)
|
||||
which provides support for RDP, the proprietary remote desktop protocol used
|
||||
by Windows Remote Deskop / Terminal Services, via the libfreerdp library.
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
Compiling and installing libguac-client-rdp
|
||||
------------------------------------------------------------
|
||||
|
||||
Please note that distribution-specific pre-compiled packages are available from
|
||||
the files section of the main project site:
|
||||
|
||||
http://sourceforge.net/projects/guacamole/files/
|
||||
|
||||
libguac-client-rdp is built using the popular GNU Automake, and thus provides
|
||||
the standard configure script.
|
||||
|
||||
1) Run configure
|
||||
|
||||
$ ./configure
|
||||
|
||||
Assuming all dependencies have been installed, this should succeed without
|
||||
errors.
|
||||
|
||||
2) Run make
|
||||
|
||||
$ make
|
||||
|
||||
libguac-client-rdp will now compile.
|
||||
|
||||
3) Install (as root)
|
||||
|
||||
# make install
|
||||
|
||||
libguac-client-rdp will install to your /usr/local/lib directory by default.
|
||||
You can change the install location by using the --prefix option for
|
||||
configure.
|
||||
|
||||
You will need to run ldconfig (as root) so that guacd can find the library
|
||||
when needed:
|
||||
|
||||
# ldconfig
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
Reporting problems
|
||||
------------------------------------------------------------
|
||||
|
||||
Please report any bugs encountered by opening a new ticket at the Trac system
|
||||
hosted at:
|
||||
|
||||
http://guac-dev.org/trac/
|
||||
|
86
protocols/rdp/configure.in
Normal file
86
protocols/rdp/configure.in
Normal file
@ -0,0 +1,86 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is libguac-client-rdp.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael Jumper.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
AC_INIT(src/client.c)
|
||||
AM_INIT_AUTOMAKE([libguac-client-rdp], 0.7.4)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB([guac], [guac_client_plugin_open],, AC_MSG_ERROR("libguac must be installed first"))
|
||||
AC_CHECK_LIB([cairo], [cairo_create],, AC_MSG_ERROR("cairo is required for drawing instructions"))
|
||||
AC_CHECK_LIB([freerdp-cache], [glyph_cache_register_callbacks],, AC_MSG_ERROR("libfreerdp-cache is required (part of FreeRDP)"))
|
||||
AC_CHECK_LIB([freerdp-core], [freerdp_new],, AC_MSG_ERROR("libfreerdp-core is required (part of FreeRDP)"))
|
||||
AC_CHECK_LIB([freerdp-channels], [freerdp_channels_new],, AC_MSG_ERROR("libfreerdp-channels is required (part of FreeRDP)"))
|
||||
AC_CHECK_LIB([freerdp-utils], [xzalloc],, AC_MSG_ERROR("libfreerdp-utils is required (part of FreeRDP)"))
|
||||
AC_CHECK_LIB([freerdp-codec], [freerdp_image_convert],, AC_MSG_ERROR("libfreerdp-codec is required (part of FreeRDP)"))
|
||||
AC_CHECK_LIB([pthread], [pthread_mutex_init],, AC_MSG_ERROR("libpthread is required"))
|
||||
|
||||
# Check for libvorbisenc
|
||||
|
||||
have_vorbisenc=yes
|
||||
AC_CHECK_HEADER(vorbis/vorbisenc.h,, [have_vorbisenc=no])
|
||||
AC_CHECK_LIB([vorbisenc], [vorbis_encode_init],, [have_vorbisenc=no])
|
||||
AM_CONDITIONAL([ENABLE_OGG], [test "x${have_vorbisenc}" = "xyes"])
|
||||
|
||||
if test "x${have_vorbisenc}" = "xno"
|
||||
then
|
||||
AC_MSG_WARN([
|
||||
--------------------------------------------
|
||||
Unable to find libvorbisenc.
|
||||
Sound will not be encoded with Ogg Vorbis.
|
||||
--------------------------------------------])
|
||||
else
|
||||
AC_DEFINE([ENABLE_OGG])
|
||||
fi
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([guacamole/client.h guacamole/guacio.h guacamole/protocol.h freerdp/locale/keyboard.h freerdp/kbd/layouts.h])
|
||||
|
||||
# Check for FreeRDP version-specific features
|
||||
AC_CHECK_MEMBERS([rdpPointer.SetDefault, rdpPointer.SetNull],
|
||||
[], [],
|
||||
[[#include <freerdp/freerdp.h>]])
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_MALLOC
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
313
protocols/rdp/guac_rdpsnd/messages.c
Normal file
313
protocols/rdp/guac_rdpsnd/messages.c
Normal file
@ -0,0 +1,313 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "service.h"
|
||||
#include "messages.h"
|
||||
#include "client.h"
|
||||
|
||||
/* MESSAGE HANDLERS */
|
||||
|
||||
void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header) {
|
||||
|
||||
int server_format_count;
|
||||
int server_version;
|
||||
int i;
|
||||
|
||||
STREAM* output_stream;
|
||||
int output_body_size;
|
||||
unsigned char* output_stream_end;
|
||||
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) audio->client->data;
|
||||
|
||||
/* Format header */
|
||||
stream_seek(input_stream, 14);
|
||||
stream_read_uint16(input_stream, server_format_count);
|
||||
stream_seek_uint8(input_stream);
|
||||
stream_read_uint16(input_stream, server_version);
|
||||
stream_seek_uint8(input_stream);
|
||||
|
||||
/* Initialize Client Audio Formats and Version PDU */
|
||||
output_stream = stream_new(24);
|
||||
stream_write_uint8(output_stream, SNDC_FORMATS);
|
||||
stream_write_uint8(output_stream, 0);
|
||||
|
||||
/* Fill in body size later */
|
||||
stream_seek_uint16(output_stream); /* offset = 0x02 */
|
||||
|
||||
/* Flags, volume, and pitch */
|
||||
stream_write_uint32(output_stream, TSSNDCAPS_ALIVE);
|
||||
stream_write_uint32(output_stream, 0);
|
||||
stream_write_uint32(output_stream, 0);
|
||||
|
||||
/* Datagram port (UDP) */
|
||||
stream_write_uint16(output_stream, 0);
|
||||
|
||||
/* Fill in format count later */
|
||||
stream_seek_uint16(output_stream); /* offset = 0x12 */
|
||||
|
||||
/* Version and padding */
|
||||
stream_write_uint8(output_stream, 0);
|
||||
stream_write_uint16(output_stream, 6);
|
||||
stream_write_uint8(output_stream, 0);
|
||||
|
||||
/* Check each server format, respond if supported */
|
||||
for (i=0; i < server_format_count; i++) {
|
||||
|
||||
unsigned char* format_start;
|
||||
|
||||
int format_tag;
|
||||
int channels;
|
||||
int rate;
|
||||
int bps;
|
||||
int body_size;
|
||||
|
||||
/* Remember position in stream */
|
||||
stream_get_mark(input_stream, format_start);
|
||||
|
||||
/* Read format */
|
||||
stream_read_uint16(input_stream, format_tag);
|
||||
stream_read_uint16(input_stream, channels);
|
||||
stream_read_uint32(input_stream, rate);
|
||||
stream_seek_uint32(input_stream);
|
||||
stream_seek_uint16(input_stream);
|
||||
stream_read_uint16(input_stream, bps);
|
||||
|
||||
/* Skip past extra data */
|
||||
stream_read_uint16(input_stream, body_size);
|
||||
stream_seek(input_stream, body_size);
|
||||
|
||||
/* If PCM, accept */
|
||||
if (format_tag == WAVE_FORMAT_PCM) {
|
||||
|
||||
/* If can fit another format, accept it */
|
||||
if (rdpsnd->format_count < GUAC_RDP_MAX_FORMATS) {
|
||||
|
||||
/* Add channel */
|
||||
int current = rdpsnd->format_count++;
|
||||
rdpsnd->formats[current].rate = rate;
|
||||
rdpsnd->formats[current].channels = channels;
|
||||
rdpsnd->formats[current].bps = bps;
|
||||
|
||||
/* Log format */
|
||||
guac_client_log_info(audio->client,
|
||||
"Accepted format: %i-bit PCM with %i channels at "
|
||||
"%i Hz",
|
||||
bps, channels, rate);
|
||||
|
||||
/* Queue format for sending as accepted */
|
||||
stream_check_size(output_stream, 18 + body_size);
|
||||
stream_write(output_stream, format_start, 18 + body_size);
|
||||
|
||||
/*
|
||||
* BEWARE that using stream_check_size means that any "marks"
|
||||
* set via stream_set_mark on output_stream are invalid.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/* Otherwise, log that we dropped one */
|
||||
else
|
||||
guac_client_log_info(audio->client,
|
||||
"Dropped valid format: %i-bit PCM with %i channels at "
|
||||
"%i Hz",
|
||||
bps, channels, rate);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Calculate size of PDU */
|
||||
output_body_size = stream_get_length(output_stream) - 4;
|
||||
stream_get_mark(output_stream, output_stream_end);
|
||||
|
||||
/* Set body size */
|
||||
stream_set_pos(output_stream, 0x02);
|
||||
stream_write_uint16(output_stream, output_body_size);
|
||||
|
||||
/* Set format count */
|
||||
stream_set_pos(output_stream, 0x12);
|
||||
stream_write_uint16(output_stream, rdpsnd->format_count);
|
||||
|
||||
/* Reposition cursor at end (necessary for message send) */
|
||||
stream_set_mark(output_stream, output_stream_end);
|
||||
|
||||
/* Send accepted formats */
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream);
|
||||
|
||||
/* If version greater than 6, must send Quality Mode PDU */
|
||||
if (server_version >= 6) {
|
||||
|
||||
/* Always send High Quality for now */
|
||||
output_stream = stream_new(8);
|
||||
stream_write_uint8(output_stream, SNDC_QUALITYMODE);
|
||||
stream_write_uint8(output_stream, 0);
|
||||
stream_write_uint16(output_stream, 4);
|
||||
stream_write_uint16(output_stream, HIGH_QUALITY);
|
||||
stream_write_uint16(output_stream, 0);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
}
|
||||
|
||||
/* server is getting a feel of the round trip time */
|
||||
void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header) {
|
||||
|
||||
int data_size;
|
||||
STREAM* output_stream;
|
||||
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) audio->client->data;
|
||||
|
||||
/* Read timestamp and data size */
|
||||
stream_read_uint16(input_stream, rdpsnd->server_timestamp);
|
||||
stream_read_uint16(input_stream, data_size);
|
||||
|
||||
/* Send training response */
|
||||
output_stream = stream_new(8);
|
||||
stream_write_uint8(output_stream, SNDC_TRAINING);
|
||||
stream_write_uint8(output_stream, 0);
|
||||
stream_write_uint16(output_stream, 4);
|
||||
stream_write_uint16(output_stream, rdpsnd->server_timestamp);
|
||||
stream_write_uint16(output_stream, data_size);
|
||||
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
svc_plugin_send((rdpSvcPlugin*) rdpsnd, output_stream);
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header) {
|
||||
|
||||
unsigned char buffer[4];
|
||||
int format;
|
||||
|
||||
/* Read wave information */
|
||||
stream_read_uint16(input_stream, rdpsnd->server_timestamp);
|
||||
stream_read_uint16(input_stream, format);
|
||||
stream_read_uint8(input_stream, rdpsnd->waveinfo_block_number);
|
||||
stream_seek(input_stream, 3);
|
||||
stream_read(input_stream, buffer, 4);
|
||||
|
||||
/*
|
||||
* Size of incoming wave data is equal to the body size field of this
|
||||
* header, less the size of a WaveInfo PDU (not including the header),
|
||||
* thus body_size - 12.
|
||||
*/
|
||||
rdpsnd->incoming_wave_size = header->body_size - 12;
|
||||
|
||||
/* Read wave in next iteration */
|
||||
rdpsnd->next_pdu_is_wave = true;
|
||||
|
||||
/* Init stream with requested format */
|
||||
audio_stream_begin(audio,
|
||||
rdpsnd->formats[format].rate,
|
||||
rdpsnd->formats[format].channels,
|
||||
rdpsnd->formats[format].bps);
|
||||
|
||||
/* Write initial 4 bytes of data */
|
||||
audio_stream_write_pcm(audio, buffer, 4);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header) {
|
||||
|
||||
rdpSvcPlugin* plugin = (rdpSvcPlugin*)rdpsnd;
|
||||
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) audio->client->data;
|
||||
|
||||
/* Wave Confirmation PDU */
|
||||
STREAM* output_stream = stream_new(8);
|
||||
|
||||
/* Get wave data */
|
||||
unsigned char* buffer = stream_get_head(input_stream) + 4;
|
||||
|
||||
/* Write rest of audio packet */
|
||||
audio_stream_write_pcm(audio, buffer, rdpsnd->incoming_wave_size);
|
||||
audio_stream_end(audio);
|
||||
|
||||
/* Write Wave Confirmation PDU */
|
||||
stream_write_uint8(output_stream, SNDC_WAVECONFIRM);
|
||||
stream_write_uint8(output_stream, 0);
|
||||
stream_write_uint16(output_stream, 4);
|
||||
stream_write_uint16(output_stream, rdpsnd->server_timestamp);
|
||||
stream_write_uint8(output_stream, rdpsnd->waveinfo_block_number);
|
||||
stream_write_uint8(output_stream, 0);
|
||||
|
||||
/* Send Wave Confirmation PDU */
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
svc_plugin_send(plugin, output_stream);
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
/* We no longer expect to receive wave data */
|
||||
rdpsnd->next_pdu_is_wave = false;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpsnd_close_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header) {
|
||||
|
||||
/* STUB: Do nothing for now */
|
||||
|
||||
}
|
||||
|
162
protocols/rdp/guac_rdpsnd/messages.h
Normal file
162
protocols/rdp/guac_rdpsnd/messages.h
Normal file
@ -0,0 +1,162 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GUAC_RDPSND_MESSAGES_H
|
||||
#define __GUAC_RDPSND_MESSAGES_H
|
||||
|
||||
/*
|
||||
* PDU Message Types
|
||||
*/
|
||||
|
||||
/**
|
||||
* Close PDU
|
||||
*/
|
||||
#define SNDC_CLOSE 1
|
||||
|
||||
/**
|
||||
* WaveInfo PDU. This PDU is sent just before wave data is sent.
|
||||
*/
|
||||
#define SNDC_WAVE 2
|
||||
|
||||
/**
|
||||
* Wave Confirm PDU. This PDU is sent in response to the WaveInfo PDU,
|
||||
* confirming it has been received and played.
|
||||
*/
|
||||
#define SNDC_WAVECONFIRM 5
|
||||
|
||||
/**
|
||||
* Training PDU. This PDU is sent by the server occasionally and must be
|
||||
* responded to with another training PDU, similar to Guac's sync message.
|
||||
*/
|
||||
#define SNDC_TRAINING 6
|
||||
|
||||
/**
|
||||
* Server Audio Formats and Version PDU. This PDU is sent by the server to
|
||||
* advertise to the client which audio formats are supported.
|
||||
*/
|
||||
#define SNDC_FORMATS 7
|
||||
|
||||
/**
|
||||
* Quality Mode PDU. This PDU must be sent by the client to select an audio
|
||||
* quality mode if the server is at least version 6.
|
||||
*/
|
||||
#define SNDC_QUALITYMODE 12
|
||||
|
||||
/*
|
||||
* Quality Modes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dynamic Quality. The server will choose the audio quality based on its
|
||||
* perception of latency.
|
||||
*/
|
||||
#define DYNAMIC_QUALITY 0x0000
|
||||
|
||||
/**
|
||||
* Medium Quality. The server prioritizes bandwidth over quality.
|
||||
*/
|
||||
#define MEDIUM_QUALITY 0x0001
|
||||
|
||||
/**
|
||||
* High Quality. The server prioritizes quality over bandwidth.
|
||||
*/
|
||||
#define HIGH_QUALITY 0x0002
|
||||
|
||||
/*
|
||||
* Capabilities
|
||||
*/
|
||||
#define TSSNDCAPS_ALIVE 1
|
||||
|
||||
/*
|
||||
* Sound Formats
|
||||
*/
|
||||
#define WAVE_FORMAT_PCM 1
|
||||
|
||||
/**
|
||||
* The header common to all RDPSND PDUs.
|
||||
*/
|
||||
typedef struct guac_rdpsnd_pdu_header {
|
||||
|
||||
/**
|
||||
* The type of message represented by this PDU (SNDC_WAVE, etc.)
|
||||
*/
|
||||
int message_type;
|
||||
|
||||
/**
|
||||
* The size of the remainder of the message.
|
||||
*/
|
||||
int body_size;
|
||||
|
||||
} guac_rdpsnd_pdu_header;
|
||||
|
||||
/**
|
||||
* Handler for the SNDC_FORMATS (Server Audio Formats and Version) PDU.
|
||||
*/
|
||||
void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header);
|
||||
|
||||
/**
|
||||
* Handler for the SNDC_TRAINING (Training) PDU.
|
||||
*/
|
||||
void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header);
|
||||
|
||||
/**
|
||||
* Handler for the SNDC_WAVE (WaveInfo) PDU.
|
||||
*/
|
||||
void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header);
|
||||
|
||||
/**
|
||||
* Handler for the SNDWAV (Wave) PDU which follows any WaveInfo PDU.
|
||||
*/
|
||||
void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header);
|
||||
|
||||
/**
|
||||
* Handler for the SNDC_CLOSE (Close) PDU.
|
||||
*/
|
||||
void guac_rdpsnd_close_handler(guac_rdpsndPlugin* rdpsnd,
|
||||
audio_stream* audio, STREAM* input_stream,
|
||||
guac_rdpsnd_pdu_header* header);
|
||||
|
||||
#endif
|
||||
|
140
protocols/rdp/guac_rdpsnd/service.c
Normal file
140
protocols/rdp/guac_rdpsnd/service.c
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "service.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
/* Define service, associate with "rdpsnd" channel */
|
||||
|
||||
DEFINE_SVC_PLUGIN(guac_rdpsnd, "rdpsnd",
|
||||
CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP)
|
||||
|
||||
|
||||
/*
|
||||
* Service Handlers
|
||||
*/
|
||||
|
||||
void guac_rdpsnd_process_connect(rdpSvcPlugin* plugin) {
|
||||
|
||||
/* Get audio stream from plugin */
|
||||
audio_stream* audio = (audio_stream*)
|
||||
plugin->channel_entry_points.pExtendedData;
|
||||
|
||||
/* Update every 10 ms */
|
||||
plugin->interval_ms = 10;
|
||||
|
||||
/* Log that sound has been loaded */
|
||||
guac_client_log_info(audio->client, "guac_rdpsnd connected.");
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpsnd_process_terminate(rdpSvcPlugin* plugin) {
|
||||
xfree(plugin);
|
||||
}
|
||||
|
||||
void guac_rdpsnd_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) {
|
||||
freerdp_event_free(event);
|
||||
}
|
||||
|
||||
void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin,
|
||||
STREAM* input_stream) {
|
||||
|
||||
guac_rdpsndPlugin* rdpsnd = (guac_rdpsndPlugin*) plugin;
|
||||
guac_rdpsnd_pdu_header header;
|
||||
|
||||
/* Get audio stream from plugin */
|
||||
audio_stream* audio = (audio_stream*)
|
||||
plugin->channel_entry_points.pExtendedData;
|
||||
|
||||
/* Read RDPSND PDU header */
|
||||
stream_read_uint8(input_stream, header.message_type);
|
||||
stream_seek_uint8(input_stream);
|
||||
stream_read_uint16(input_stream, header.body_size);
|
||||
|
||||
/*
|
||||
* If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously),
|
||||
* ignore the header and parse as a Wave PDU.
|
||||
*/
|
||||
if (rdpsnd->next_pdu_is_wave) {
|
||||
guac_rdpsnd_wave_handler(rdpsnd, audio, input_stream, &header);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch message to standard handlers */
|
||||
switch (header.message_type) {
|
||||
|
||||
/* Server Audio Formats and Version PDU */
|
||||
case SNDC_FORMATS:
|
||||
guac_rdpsnd_formats_handler(rdpsnd, audio,
|
||||
input_stream, &header);
|
||||
break;
|
||||
|
||||
/* Training PDU */
|
||||
case SNDC_TRAINING:
|
||||
guac_rdpsnd_training_handler(rdpsnd, audio,
|
||||
input_stream, &header);
|
||||
break;
|
||||
|
||||
/* WaveInfo PDU */
|
||||
case SNDC_WAVE:
|
||||
guac_rdpsnd_wave_info_handler(rdpsnd, audio,
|
||||
input_stream, &header);
|
||||
break;
|
||||
|
||||
/* Close PDU */
|
||||
case SNDC_CLOSE:
|
||||
guac_rdpsnd_close_handler(rdpsnd, audio,
|
||||
input_stream, &header);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
146
protocols/rdp/guac_rdpsnd/service.h
Normal file
146
protocols/rdp/guac_rdpsnd/service.h
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GUAC_RDPSND_SERVICE_H
|
||||
#define __GUAC_RDPSND_SERVICE_H
|
||||
|
||||
/**
|
||||
* The maximum number of PCM formats to accept during the initial RDPSND
|
||||
* handshake with the RDP server.
|
||||
*/
|
||||
#define GUAC_RDP_MAX_FORMATS 16
|
||||
|
||||
|
||||
/**
|
||||
* Abstract representation of a PCM format, including the sample rate, number
|
||||
* of channels, and bits per sample.
|
||||
*/
|
||||
typedef struct guac_pcm_format {
|
||||
|
||||
/**
|
||||
* The sample rate of this PCM format.
|
||||
*/
|
||||
int rate;
|
||||
|
||||
/**
|
||||
* The number off channels used by this PCM format. This will typically
|
||||
* be 1 or 2.
|
||||
*/
|
||||
int channels;
|
||||
|
||||
/**
|
||||
* The number of bits per sample within this PCM format. This should be
|
||||
* either 8 or 16.
|
||||
*/
|
||||
int bps;
|
||||
|
||||
} guac_pcm_format;
|
||||
|
||||
|
||||
/**
|
||||
* Structure representing the current state of the Guacamole RDPSND plugin for
|
||||
* FreeRDP.
|
||||
*/
|
||||
typedef struct guac_rdpsndPlugin {
|
||||
|
||||
/**
|
||||
* The FreeRDP parts of this plugin. This absolutely MUST be first.
|
||||
* FreeRDP depends on accessing this structure as if it were an instance
|
||||
* of rdpSvcPlugin.
|
||||
*/
|
||||
rdpSvcPlugin plugin;
|
||||
|
||||
/**
|
||||
* The block number of the last SNDC_WAVE (WaveInfo) PDU received.
|
||||
*/
|
||||
int waveinfo_block_number;
|
||||
|
||||
/**
|
||||
* Whether the next PDU coming is a SNDWAVE (Wave) PDU. Wave PDUs do not
|
||||
* have headers, and are indicated by the receipt of a WaveInfo PDU.
|
||||
*/
|
||||
int next_pdu_is_wave;
|
||||
|
||||
/**
|
||||
* The size, in bytes, of the wave data in the coming Wave PDU, if any.
|
||||
*/
|
||||
int incoming_wave_size;
|
||||
|
||||
/**
|
||||
* The last received server timestamp.
|
||||
*/
|
||||
int server_timestamp;
|
||||
|
||||
/**
|
||||
* All formats agreed upon by server and client during the initial format
|
||||
* exchange. All of these formats will be PCM, which is the only format
|
||||
* guaranteed to be supported (based on the official RDP documentation).
|
||||
*/
|
||||
guac_pcm_format formats[GUAC_RDP_MAX_FORMATS];
|
||||
|
||||
/**
|
||||
* The total number of formats.
|
||||
*/
|
||||
int format_count;
|
||||
|
||||
} guac_rdpsndPlugin;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when this plugin is loaded by FreeRDP.
|
||||
*/
|
||||
void guac_rdpsnd_process_connect(rdpSvcPlugin* plugin);
|
||||
|
||||
/**
|
||||
* Handler called when this plugin receives data along its designated channel.
|
||||
*/
|
||||
void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin,
|
||||
STREAM* input_stream);
|
||||
|
||||
/**
|
||||
* Handler called when this plugin is being unloaded.
|
||||
*/
|
||||
void guac_rdpsnd_process_terminate(rdpSvcPlugin* plugin);
|
||||
|
||||
/**
|
||||
* Handler called when this plugin receives an event. For the sake of RDPSND,
|
||||
* all events will be ignored and simply free'd.
|
||||
*/
|
||||
void guac_rdpsnd_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event);
|
||||
|
||||
#endif
|
||||
|
212
protocols/rdp/include/audio.h
Normal file
212
protocols/rdp/include/audio.h
Normal file
@ -0,0 +1,212 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GUAC_TEST_AUDIO_H
|
||||
#define __GUAC_TEST_AUDIO_H
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/stream.h>
|
||||
|
||||
typedef struct audio_stream audio_stream;
|
||||
|
||||
/**
|
||||
* Handler which is called when the audio stream is opened.
|
||||
*/
|
||||
typedef void audio_encoder_begin_handler(audio_stream* audio);
|
||||
|
||||
/**
|
||||
* Handler which is called when the audio stream is closed.
|
||||
*/
|
||||
typedef void audio_encoder_end_handler(audio_stream* audio);
|
||||
|
||||
/**
|
||||
* Handler which is called when the audio stream is flushed.
|
||||
*/
|
||||
typedef void audio_encoder_write_handler(audio_stream* audio,
|
||||
unsigned char* pcm_data, int length);
|
||||
|
||||
/**
|
||||
* Arbitrary audio codec encoder.
|
||||
*/
|
||||
typedef struct audio_encoder {
|
||||
|
||||
/**
|
||||
* The mimetype of the audio data encoded by this audio
|
||||
* encoder.
|
||||
*/
|
||||
const char* mimetype;
|
||||
|
||||
/**
|
||||
* Handler which will be called when the audio stream is opened.
|
||||
*/
|
||||
audio_encoder_begin_handler* begin_handler;
|
||||
|
||||
/**
|
||||
* Handler which will be called when the audio stream is flushed.
|
||||
*/
|
||||
audio_encoder_write_handler* write_handler;
|
||||
|
||||
/**
|
||||
* Handler which will be called when the audio stream is closed.
|
||||
*/
|
||||
audio_encoder_end_handler* end_handler;
|
||||
|
||||
} audio_encoder;
|
||||
|
||||
/**
|
||||
* Basic audio stream. PCM data is added to the stream. When the stream is
|
||||
* flushed, a write handler receives PCM data packets and, presumably, streams
|
||||
* them to the guac_stream provided.
|
||||
*/
|
||||
struct audio_stream {
|
||||
|
||||
/**
|
||||
* PCM data buffer, 16-bit samples, 2-channel, 44100 Hz.
|
||||
*/
|
||||
unsigned char* pcm_data;
|
||||
|
||||
/**
|
||||
* Number of bytes in buffer.
|
||||
*/
|
||||
int used;
|
||||
|
||||
/**
|
||||
* Maximum number of bytes in buffer.
|
||||
*/
|
||||
int length;
|
||||
|
||||
/**
|
||||
* Encoded audio data buffer, as written by the encoder.
|
||||
*/
|
||||
unsigned char* encoded_data;
|
||||
|
||||
/**
|
||||
* Number of bytes in the encoded data buffer.
|
||||
*/
|
||||
int encoded_data_used;
|
||||
|
||||
/**
|
||||
* Maximum number of bytes in the encoded data buffer.
|
||||
*/
|
||||
int encoded_data_length;
|
||||
|
||||
/**
|
||||
* Arbitrary codec encoder. When the PCM buffer is flushed, PCM data will
|
||||
* be sent to this encoder.
|
||||
*/
|
||||
audio_encoder* encoder;
|
||||
|
||||
/**
|
||||
* The client associated with this audio stream.
|
||||
*/
|
||||
guac_client* client;
|
||||
|
||||
/**
|
||||
* The actual stream associated with this audio stream.
|
||||
*/
|
||||
guac_stream* stream;
|
||||
|
||||
/**
|
||||
* The number of samples per second of PCM data sent to this stream.
|
||||
*/
|
||||
int rate;
|
||||
|
||||
/**
|
||||
* The number of audio channels per sample of PCM data. Legal values are
|
||||
* 1 or 2.
|
||||
*/
|
||||
int channels;
|
||||
|
||||
/**
|
||||
* The number of bits per sample per channel for PCM data. Legal values are
|
||||
* 8 or 16.
|
||||
*/
|
||||
int bps;
|
||||
|
||||
/**
|
||||
* The number of PCM bytes written since the audio chunk began.
|
||||
*/
|
||||
int pcm_bytes_written;
|
||||
|
||||
/**
|
||||
* Encoder-specific state data.
|
||||
*/
|
||||
void* data;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocates a new audio stream.
|
||||
*/
|
||||
audio_stream* audio_stream_alloc(guac_client* client,
|
||||
audio_encoder* encoder);
|
||||
|
||||
/**
|
||||
* Frees the given audio stream.
|
||||
*/
|
||||
void audio_stream_free(audio_stream* stream);
|
||||
|
||||
/**
|
||||
* Begins a new audio stream.
|
||||
*/
|
||||
void audio_stream_begin(audio_stream* stream, int rate, int channels, int bps);
|
||||
|
||||
/**
|
||||
* Ends the current audio stream.
|
||||
*/
|
||||
void audio_stream_end(audio_stream* stream);
|
||||
|
||||
/**
|
||||
* Writes PCM data to the given audio stream.
|
||||
*/
|
||||
void audio_stream_write_pcm(audio_stream* stream,
|
||||
unsigned char* data, int length);
|
||||
|
||||
/**
|
||||
* Flushes the given audio stream.
|
||||
*/
|
||||
void audio_stream_flush(audio_stream* stream);
|
||||
|
||||
/**
|
||||
* Appends arbitrarily-encoded data to the encoded_data buffer
|
||||
* within the given audio stream.
|
||||
*/
|
||||
void audio_stream_write_encoded(audio_stream* audio,
|
||||
unsigned char* data, int length);
|
||||
|
||||
#endif
|
||||
|
221
protocols/rdp/include/client.h
Normal file
221
protocols/rdp/include/client.h
Normal file
@ -0,0 +1,221 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_CLIENT_H
|
||||
#define _GUAC_RDP_CLIENT_H
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
/**
|
||||
* The default RDP port.
|
||||
*/
|
||||
#define RDP_DEFAULT_PORT 3389
|
||||
|
||||
/**
|
||||
* Default screen width, in pixels.
|
||||
*/
|
||||
#define RDP_DEFAULT_WIDTH 1024
|
||||
|
||||
/**
|
||||
* Default screen height, in pixels.
|
||||
*/
|
||||
#define RDP_DEFAULT_HEIGHT 768
|
||||
|
||||
/**
|
||||
* Default color depth, in bits.
|
||||
*/
|
||||
#define RDP_DEFAULT_DEPTH 16
|
||||
|
||||
/**
|
||||
* Client data that will remain accessible through the guac_client.
|
||||
* This should generally include data commonly used by Guacamole handlers.
|
||||
*/
|
||||
typedef struct rdp_guac_client_data {
|
||||
|
||||
/**
|
||||
* Pointer to the FreeRDP client instance handling the current connection.
|
||||
*/
|
||||
freerdp* rdp_inst;
|
||||
|
||||
/**
|
||||
* The settings structure associated with the FreeRDP client instance
|
||||
* handling the current connection.
|
||||
*/
|
||||
rdpSettings* settings;
|
||||
|
||||
/**
|
||||
* Button mask containing the OR'd value of all currently pressed buttons.
|
||||
*/
|
||||
int mouse_button_mask;
|
||||
|
||||
/**
|
||||
* Cairo surface which will receive all TRANSPARENT glyphs.
|
||||
*/
|
||||
cairo_surface_t* trans_glyph_surface;
|
||||
|
||||
/**
|
||||
* Cairo surface which will receive all OPAQUE glyphs.
|
||||
*/
|
||||
cairo_surface_t* opaque_glyph_surface;
|
||||
|
||||
/**
|
||||
* The current Cairo surface which will receive all drawn glyphs,
|
||||
* depending on whether we are currently drawing transparent or
|
||||
* opaque glyphs.
|
||||
*/
|
||||
cairo_surface_t* glyph_surface;
|
||||
|
||||
/**
|
||||
* Cairo instance for drawing to the current glyph surface.
|
||||
*/
|
||||
cairo_t* glyph_cairo;
|
||||
|
||||
/**
|
||||
* The Guacamole layer that GDI operations should draw to. RDP messages
|
||||
* exist which change this surface to allow drawing to occur off-screen.
|
||||
*/
|
||||
const guac_layer* current_surface;
|
||||
|
||||
/**
|
||||
* Whether graphical operations are restricted to a specific bounding
|
||||
* rectangle.
|
||||
*/
|
||||
int bounded;
|
||||
|
||||
/**
|
||||
* The X coordinate of the upper-left corner of the bounding rectangle,
|
||||
* if any.
|
||||
*/
|
||||
int bounds_left;
|
||||
|
||||
/**
|
||||
* The Y coordinate of the upper-left corner of the bounding rectangle,
|
||||
* if any.
|
||||
*/
|
||||
int bounds_top;
|
||||
|
||||
/**
|
||||
* The X coordinate of the lower-right corner of the bounding rectangle,
|
||||
* if any.
|
||||
*/
|
||||
int bounds_right;
|
||||
|
||||
/**
|
||||
* The Y coordinate of the lower-right corner of the bounding rectangle,
|
||||
* if any.
|
||||
*/
|
||||
int bounds_bottom;
|
||||
|
||||
/**
|
||||
* The keymap to use when translating keysyms into scancodes or sequences
|
||||
* of scancodes for RDP.
|
||||
*/
|
||||
guac_rdp_static_keymap keymap;
|
||||
|
||||
/**
|
||||
* The state of all keys, based on whether events for pressing/releasing
|
||||
* particular keysyms have been received. This is necessary in order to
|
||||
* determine which keys must be released/pressed when a particular
|
||||
* keysym can only be typed through a sequence of scancodes (such as
|
||||
* an Alt-code) because the server-side keymap does not support that
|
||||
* keysym.
|
||||
*/
|
||||
guac_rdp_keysym_state_map keysym_state;
|
||||
|
||||
/**
|
||||
* The current text (NOT Unicode) clipboard contents.
|
||||
*/
|
||||
char* clipboard;
|
||||
|
||||
/**
|
||||
* Whether audio is enabled.
|
||||
*/
|
||||
int audio_enabled;
|
||||
|
||||
/**
|
||||
* Audio output, if any.
|
||||
*/
|
||||
audio_stream* audio;
|
||||
|
||||
/**
|
||||
* Lock which is locked and unlocked for each update.
|
||||
*/
|
||||
pthread_mutex_t update_lock;
|
||||
|
||||
/**
|
||||
* Lock which is locked and unlocked for each RDP message.
|
||||
*/
|
||||
pthread_mutex_t rdp_lock;
|
||||
|
||||
pthread_mutexattr_t attributes;
|
||||
|
||||
} rdp_guac_client_data;
|
||||
|
||||
/**
|
||||
* Client data that will remain accessible through the RDP context.
|
||||
* This should generally include data commonly used by FreeRDP handlers.
|
||||
*/
|
||||
typedef struct rdp_freerdp_context {
|
||||
|
||||
/**
|
||||
* The parent context. THIS MUST BE THE FIRST ELEMENT.
|
||||
*/
|
||||
rdpContext _p;
|
||||
|
||||
/**
|
||||
* Pointer to the guac_client instance handling the RDP connection with
|
||||
* this context.
|
||||
*/
|
||||
guac_client* client;
|
||||
|
||||
/**
|
||||
* Color conversion structure to be used to convert RDP images to PNGs.
|
||||
*/
|
||||
CLRCONV* clrconv;
|
||||
|
||||
} rdp_freerdp_context;
|
||||
|
||||
#endif
|
||||
|
0
protocols/rdp/include/config.h
Normal file
0
protocols/rdp/include/config.h
Normal file
76
protocols/rdp/include/default_pointer.h
Normal file
76
protocols/rdp/include/default_pointer.h
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_DEFAULT_POINTER_H
|
||||
#define _GUAC_RDP_DEFAULT_POINTER_H
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
#include <guacamole/client.h>
|
||||
|
||||
/**
|
||||
* Width of the embedded mouse cursor graphic.
|
||||
*/
|
||||
extern const int guac_rdp_default_pointer_width;
|
||||
|
||||
/**
|
||||
* Height of the embedded mouse cursor graphic.
|
||||
*/
|
||||
extern const int guac_rdp_default_pointer_height;
|
||||
|
||||
/**
|
||||
* Number of bytes in each row of the embedded mouse cursor graphic.
|
||||
*/
|
||||
extern const int guac_rdp_default_pointer_stride;
|
||||
|
||||
/**
|
||||
* The Cairo grapic format of the mouse cursor graphic.
|
||||
*/
|
||||
extern const cairo_format_t guac_rdp_default_pointer_format;
|
||||
|
||||
/**
|
||||
* Embedded mouse cursor graphic.
|
||||
*/
|
||||
extern unsigned char guac_rdp_default_pointer[];
|
||||
|
||||
/**
|
||||
* Set the cursor of the remote display to the embedded cursor graphic.
|
||||
*
|
||||
* @param client The guac_client to send the cursor to.
|
||||
*/
|
||||
void guac_rdp_set_default_pointer(guac_client* client);
|
||||
|
||||
#endif
|
50
protocols/rdp/include/guac_handlers.h
Normal file
50
protocols/rdp/include/guac_handlers.h
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_GUAC_HANDLERS_H
|
||||
#define _GUAC_RDP_GUAC_HANDLERS_H
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
int rdp_guac_client_free_handler(guac_client* client);
|
||||
int rdp_guac_client_handle_messages(guac_client* client);
|
||||
int rdp_guac_client_mouse_handler(guac_client* client, int x, int y, int mask);
|
||||
int rdp_guac_client_key_handler(guac_client* client, int keysym, int pressed);
|
||||
int rdp_guac_client_clipboard_handler(guac_client* client, char* data);
|
||||
|
||||
#endif
|
||||
|
67
protocols/rdp/include/ogg_encoder.h
Normal file
67
protocols/rdp/include/ogg_encoder.h
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GUAC_OGG_ENCODER_H
|
||||
#define __GUAC_OGG_ENCODER_H
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
#include <vorbis/vorbisenc.h>
|
||||
|
||||
typedef struct ogg_encoder_state {
|
||||
|
||||
/**
|
||||
* Ogg state
|
||||
*/
|
||||
ogg_stream_state ogg_state;
|
||||
ogg_page ogg_page;
|
||||
ogg_packet ogg_packet;
|
||||
|
||||
/**
|
||||
* Vorbis state
|
||||
*/
|
||||
vorbis_info info;
|
||||
vorbis_comment comment;
|
||||
vorbis_dsp_state vorbis_state;
|
||||
vorbis_block vorbis_block;
|
||||
|
||||
} ogg_encoder_state;
|
||||
|
||||
extern audio_encoder* ogg_encoder;
|
||||
|
||||
#endif
|
||||
|
71
protocols/rdp/include/rdp_bitmap.h
Normal file
71
protocols/rdp/include/rdp_bitmap.h
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_RDP_BITMAP_H
|
||||
#define _GUAC_RDP_RDP_BITMAP_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
typedef struct guac_rdp_bitmap {
|
||||
|
||||
/**
|
||||
* FreeRDP bitmap data - MUST GO FIRST.
|
||||
*/
|
||||
rdpBitmap bitmap;
|
||||
|
||||
/**
|
||||
* Guacamole layer containing cached image data.
|
||||
*/
|
||||
guac_layer* layer;
|
||||
|
||||
/**
|
||||
* The number of times a bitmap has been used.
|
||||
*/
|
||||
int used;
|
||||
|
||||
} guac_rdp_bitmap;
|
||||
|
||||
void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap);
|
||||
void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap);
|
||||
void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed);
|
||||
void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap);
|
||||
void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap);
|
||||
void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, boolean primary);
|
||||
|
||||
#endif
|
56
protocols/rdp/include/rdp_cliprdr.h
Normal file
56
protocols/rdp/include/rdp_cliprdr.h
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GUAC_RDP_RDP_CLIPRDR_H
|
||||
#define __GUAC_RDP_RDP_CLIPRDR_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
void guac_rdp_process_cliprdr_event(guac_client* client, RDP_EVENT* event);
|
||||
void guac_rdp_process_cb_monitor_ready(guac_client* client, RDP_EVENT* event);
|
||||
|
||||
void guac_rdp_process_cb_format_list(guac_client* client,
|
||||
RDP_CB_FORMAT_LIST_EVENT* event);
|
||||
|
||||
void guac_rdp_process_cb_data_request(guac_client* client,
|
||||
RDP_CB_DATA_REQUEST_EVENT* event);
|
||||
|
||||
void guac_rdp_process_cb_data_response(guac_client* client,
|
||||
RDP_CB_DATA_RESPONSE_EVENT* event);
|
||||
|
||||
#endif
|
||||
|
56
protocols/rdp/include/rdp_gdi.h
Normal file
56
protocols/rdp/include/rdp_gdi.h
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_RDP_GDI_H
|
||||
#define _GUAC_RDP_RDP_GDI_H
|
||||
|
||||
#include <guacamole/protocol.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client,
|
||||
int rop3);
|
||||
|
||||
void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt);
|
||||
void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt);
|
||||
void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt);
|
||||
void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt);
|
||||
void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect);
|
||||
void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette);
|
||||
void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds);
|
||||
void guac_rdp_gdi_end_paint(rdpContext* context);
|
||||
|
||||
#endif
|
67
protocols/rdp/include/rdp_glyph.h
Normal file
67
protocols/rdp/include/rdp_glyph.h
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_RDP_GLYPH_H
|
||||
#define _GUAC_RDP_RDP_GLYPH_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
typedef struct guac_rdp_glyph {
|
||||
|
||||
/**
|
||||
* FreeRDP glyph data - MUST GO FIRST.
|
||||
*/
|
||||
rdpGlyph glyph;
|
||||
|
||||
/**
|
||||
* Cairo surface layer containing cached image data.
|
||||
*/
|
||||
cairo_surface_t* surface;
|
||||
|
||||
} guac_rdp_glyph;
|
||||
|
||||
void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph);
|
||||
void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y);
|
||||
void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph);
|
||||
void guac_rdp_glyph_begindraw(rdpContext* context,
|
||||
int x, int y, int width, int height, uint32 fgcolor, uint32 bgcolor);
|
||||
void guac_rdp_glyph_enddraw(rdpContext* context,
|
||||
int x, int y, int width, int height, uint32 fgcolor, uint32 bgcolor);
|
||||
|
||||
#endif
|
230
protocols/rdp/include/rdp_keymap.h
Normal file
230
protocols/rdp/include/rdp_keymap.h
Normal file
@ -0,0 +1,230 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_RDP_KEYMAP_H
|
||||
#define _GUAC_RDP_RDP_KEYMAP_H
|
||||
|
||||
#ifdef HAVE_FREERDP_LOCALE_KEYBOARD_H
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#else
|
||||
#include <freerdp/kbd/layouts.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents a keysym-to-scancode mapping for RDP, with extra information
|
||||
* about the state of prerequisite keysyms.
|
||||
*/
|
||||
typedef struct guac_rdp_keysym_desc {
|
||||
|
||||
/**
|
||||
* The keysym being mapped.
|
||||
*/
|
||||
int keysym;
|
||||
|
||||
/**
|
||||
* The scancode this keysym maps to.
|
||||
*/
|
||||
int scancode;
|
||||
|
||||
/**
|
||||
* Required RDP-specific flags.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/**
|
||||
* Null-terminated list of keysyms which must be down for this keysym
|
||||
* to be properly typed.
|
||||
*/
|
||||
const int* set_keysyms;
|
||||
|
||||
/**
|
||||
* Null-terminated list of keysyms which must be up for this keysym
|
||||
* to be properly typed.
|
||||
*/
|
||||
const int* clear_keysyms;
|
||||
|
||||
} guac_rdp_keysym_desc;
|
||||
|
||||
/**
|
||||
* Hierarchical keysym mapping
|
||||
*/
|
||||
typedef struct guac_rdp_keymap guac_rdp_keymap;
|
||||
struct guac_rdp_keymap {
|
||||
|
||||
/**
|
||||
* The parent mapping this map will inherit its initial mapping from.
|
||||
* Any other mapping information will add to or override the mapping
|
||||
* inherited from the parent.
|
||||
*/
|
||||
const guac_rdp_keymap* parent;
|
||||
|
||||
/**
|
||||
* Descriptive name of this keymap
|
||||
*/
|
||||
const char* name;
|
||||
|
||||
/**
|
||||
* Null-terminated array of scancode mappings.
|
||||
*/
|
||||
const guac_rdp_keysym_desc* mapping;
|
||||
|
||||
/**
|
||||
* FreeRDP keyboard layout associated with this
|
||||
* keymap. If this keymap is selected, this layout
|
||||
* will be requested from the server.
|
||||
*/
|
||||
const uint32 freerdp_keyboard_layout;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Static mapping from keysyms to scancodes.
|
||||
*/
|
||||
typedef guac_rdp_keysym_desc guac_rdp_static_keymap[0x200][0x100];
|
||||
|
||||
/**
|
||||
* Mapping from keysym to current state
|
||||
*/
|
||||
typedef int guac_rdp_keysym_state_map[0x200][0x100];
|
||||
|
||||
/**
|
||||
* US English keymap.
|
||||
*/
|
||||
extern const guac_rdp_keymap guac_rdp_keymap_en_us;
|
||||
|
||||
/**
|
||||
* German keymap.
|
||||
*/
|
||||
extern const guac_rdp_keymap guac_rdp_keymap_de_de;
|
||||
|
||||
/**
|
||||
* French keymap.
|
||||
*/
|
||||
extern const guac_rdp_keymap guac_rdp_keymap_fr_fr;
|
||||
|
||||
/**
|
||||
* Failsafe (Unicode events for all printable characters) keymap.
|
||||
*/
|
||||
extern const guac_rdp_keymap guac_rdp_keymap_failsafe;
|
||||
|
||||
/**
|
||||
* Common, base keymap for non-printable keys.
|
||||
*/
|
||||
extern const guac_rdp_keymap guac_rdp_keymap_base;
|
||||
|
||||
/**
|
||||
* Simple macro for determing whether a keysym can be stored (or retrieved)
|
||||
* from any keymap.
|
||||
*/
|
||||
#define GUAC_RDP_KEYSYM_STORABLE(keysym) ((keysym) <= 0xFFFF || ((keysym) & 0xFFFF0000) == 0x01000000)
|
||||
|
||||
/**
|
||||
* Simple macro for referencing the mapped value of a scancode for a given
|
||||
* keysym. The idea here is that a keysym of the form 0xABCD will map to
|
||||
* mapping[0xAB][0xCD] while a keysym of the form 0x100ABCD will map to
|
||||
* mapping[0x1AB][0xCD].
|
||||
*/
|
||||
#define GUAC_RDP_KEYSYM_LOOKUP(keysym_mapping, keysym) ( \
|
||||
(keysym_mapping) \
|
||||
[(((keysym) & 0xFF00) >> 8) | ((keysym) >> 16)] \
|
||||
[(keysym) & 0xFF] \
|
||||
)
|
||||
|
||||
/**
|
||||
* Keysym string containing only the left "shift" key.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_SHIFT[];
|
||||
|
||||
/**
|
||||
* Keysym string containing both "shift" keys.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALL_SHIFT[];
|
||||
|
||||
/**
|
||||
* Keysym string containing only the right "alt" key (AltGr).
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALTGR[];
|
||||
|
||||
/**
|
||||
* Keysym string containing the right "alt" key (AltGr) and
|
||||
* left shift.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_SHIFT_ALTGR[];
|
||||
|
||||
/**
|
||||
* Keysym string containing the right "alt" key (AltGr) and
|
||||
* both shift keys.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALL_SHIFT_ALTGR[];
|
||||
|
||||
/**
|
||||
* Keysym string containing only the left "ctrl" key.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_CTRL[];
|
||||
|
||||
/**
|
||||
* Keysym string containing both "ctrl" keys.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALL_CTRL[];
|
||||
|
||||
/**
|
||||
* Keysym string containing only the left "alt" key.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALT[];
|
||||
|
||||
/**
|
||||
* Keysym string containing both "alt" keys.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALL_ALT[];
|
||||
|
||||
/**
|
||||
* Keysym string containing the left "alt" and left "ctrl" keys
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_CTRL_ALT[];
|
||||
|
||||
/**
|
||||
* Keysym string containing all modifier keys.
|
||||
*/
|
||||
extern const int GUAC_KEYSYMS_ALL_MODIFIERS[];
|
||||
|
||||
/**
|
||||
* NULL-terminated array of all keymaps.
|
||||
*/
|
||||
extern const guac_rdp_keymap* GUAC_KEYMAPS[];
|
||||
|
||||
#endif
|
||||
|
66
protocols/rdp/include/rdp_pointer.h
Normal file
66
protocols/rdp/include/rdp_pointer.h
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David PHAM-VAN <d.pham-van@ulteo.com> Ulteo SAS - http://www.ulteo.com
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _GUAC_RDP_RDP_POINTER_H
|
||||
#define _GUAC_RDP_RDP_POINTER_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
typedef struct guac_rdp_pointer {
|
||||
|
||||
/**
|
||||
* FreeRDP pointer data - MUST GO FIRST.
|
||||
*/
|
||||
rdpPointer pointer;
|
||||
|
||||
/**
|
||||
* Guacamole layer containing cached image data.
|
||||
*/
|
||||
guac_layer* layer;
|
||||
|
||||
} guac_rdp_pointer;
|
||||
|
||||
void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer);
|
||||
void guac_rdp_pointer_set(rdpContext* context, rdpPointer* pointer);
|
||||
void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer);
|
||||
void guac_rdp_pointer_set_null(rdpContext* context);
|
||||
void guac_rdp_pointer_set_default(rdpContext* context);
|
||||
|
||||
#endif
|
144
protocols/rdp/include/wav_encoder.h
Normal file
144
protocols/rdp/include/wav_encoder.h
Normal file
@ -0,0 +1,144 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GUAC_WAV_ENCODER_H
|
||||
#define __GUAC_WAV_ENCODER_H
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
typedef struct wav_encoder_riff_header {
|
||||
|
||||
/**
|
||||
* The RIFF chunk header, normally the string "RIFF".
|
||||
*/
|
||||
unsigned char chunk_id[4];
|
||||
|
||||
/**
|
||||
* Size of the entire file, not including chunk_id or chunk_size.
|
||||
*/
|
||||
unsigned char chunk_size[4];
|
||||
|
||||
/**
|
||||
* The format of this file, normally the string "WAVE".
|
||||
*/
|
||||
unsigned char chunk_format[4];
|
||||
|
||||
} wav_encoder_riff_header;
|
||||
|
||||
typedef struct wav_encoder_fmt_header {
|
||||
|
||||
/**
|
||||
* ID of this subchunk. For the fmt subchunk, this should be "fmt ".
|
||||
*/
|
||||
unsigned char subchunk_id[4];
|
||||
|
||||
/**
|
||||
* The size of the rest of this subchunk. For PCM, this will be 16.
|
||||
*/
|
||||
unsigned char subchunk_size[4];
|
||||
|
||||
/**
|
||||
* Format of this subchunk. For PCM, this will be 1.
|
||||
*/
|
||||
unsigned char subchunk_format[2];
|
||||
|
||||
/**
|
||||
* The number of channels in the PCM data.
|
||||
*/
|
||||
unsigned char subchunk_channels[2];
|
||||
|
||||
/**
|
||||
* The sample rate of the PCM data.
|
||||
*/
|
||||
unsigned char subchunk_sample_rate[4];
|
||||
|
||||
/**
|
||||
* The sample rate of the PCM data in bytes per second.
|
||||
*/
|
||||
unsigned char subchunk_byte_rate[4];
|
||||
|
||||
/**
|
||||
* The number of bytes per sample.
|
||||
*/
|
||||
unsigned char subchunk_block_align[2];
|
||||
|
||||
/**
|
||||
* The number of bits per sample.
|
||||
*/
|
||||
unsigned char subchunk_bps[2];
|
||||
|
||||
} wav_encoder_fmt_header;
|
||||
|
||||
typedef struct wav_encoder_state {
|
||||
|
||||
/**
|
||||
* Arbitrary PCM data available for writing when the overall WAV is
|
||||
* flushed.
|
||||
*/
|
||||
unsigned char* data_buffer;
|
||||
|
||||
/**
|
||||
* The number of bytes currently present in the data buffer.
|
||||
*/
|
||||
int used;
|
||||
|
||||
/**
|
||||
* The total number of bytes that can be written into the data buffer
|
||||
* without requiring resizing.
|
||||
*/
|
||||
int length;
|
||||
|
||||
} wav_encoder_state;
|
||||
|
||||
typedef struct wav_encoder_data_header {
|
||||
|
||||
/**
|
||||
* ID of this subchunk. For the data subchunk, this should be "data".
|
||||
*/
|
||||
unsigned char subchunk_id[4];
|
||||
|
||||
/**
|
||||
* The number of bytes in the PCM data.
|
||||
*/
|
||||
unsigned char subchunk_size[4];
|
||||
|
||||
} wav_encoder_data_header;
|
||||
|
||||
extern audio_encoder* wav_encoder;
|
||||
|
||||
#endif
|
||||
|
12
protocols/rdp/m4/README
Normal file
12
protocols/rdp/m4/README
Normal file
@ -0,0 +1,12 @@
|
||||
This file exists such that the m4/ directory will be created when cloning the
|
||||
git repository.
|
||||
|
||||
The m4/ directory is not directly used by this project, but libtoolize
|
||||
populates this directory with files, recommending that the directory be
|
||||
included in the macro search path for aclocal.
|
||||
|
||||
Because autoreconf runs aclocal before libtoolize, this directory will not
|
||||
exist when autoreconf is run, triggering an error from aclocal.
|
||||
|
||||
Creating this directory (and keeping this file in it as a placeholder)
|
||||
prevents this error.
|
179
protocols/rdp/src/audio.c
Normal file
179
protocols/rdp/src/audio.c
Normal file
@ -0,0 +1,179 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/stream.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "client.h"
|
||||
|
||||
audio_stream* audio_stream_alloc(guac_client* client, audio_encoder* encoder) {
|
||||
|
||||
/* Allocate stream */
|
||||
audio_stream* audio = (audio_stream*) malloc(sizeof(audio_stream));
|
||||
audio->client = client;
|
||||
|
||||
/* Reset buffer stats */
|
||||
audio->used = 0;
|
||||
audio->length = 0x40000;
|
||||
|
||||
audio->encoded_data_used = 0;
|
||||
audio->encoded_data_length = 0x40000;
|
||||
|
||||
/* Allocate buffers */
|
||||
audio->pcm_data = malloc(audio->length);
|
||||
audio->encoded_data = malloc(audio->encoded_data_length);
|
||||
|
||||
/* Assign encoder */
|
||||
audio->encoder = encoder;
|
||||
audio->stream = guac_client_alloc_stream(client);
|
||||
|
||||
return audio;
|
||||
}
|
||||
|
||||
void audio_stream_begin(audio_stream* audio, int rate, int channels, int bps) {
|
||||
|
||||
/* Load PCM properties */
|
||||
audio->rate = rate;
|
||||
audio->channels = channels;
|
||||
audio->bps = bps;
|
||||
|
||||
/* Reset write counter */
|
||||
audio->pcm_bytes_written = 0;
|
||||
|
||||
/* Call handler */
|
||||
audio->encoder->begin_handler(audio);
|
||||
|
||||
}
|
||||
|
||||
void audio_stream_end(audio_stream* audio) {
|
||||
|
||||
double duration;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) audio->client->data;
|
||||
|
||||
/* Flush stream and finish encoding */
|
||||
audio_stream_flush(audio);
|
||||
audio->encoder->end_handler(audio);
|
||||
|
||||
/* Calculate duration of PCM data */
|
||||
duration = ((double) (audio->pcm_bytes_written * 1000 * 8))
|
||||
/ audio->rate / audio->channels / audio->bps;
|
||||
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* Send audio */
|
||||
guac_protocol_send_audio(audio->stream->socket,
|
||||
0, audio->encoder->mimetype,
|
||||
duration, audio->encoded_data, audio->encoded_data_used);
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
|
||||
/* Clear data */
|
||||
audio->encoded_data_used = 0;
|
||||
|
||||
}
|
||||
|
||||
void audio_stream_free(audio_stream* audio) {
|
||||
free(audio->pcm_data);
|
||||
free(audio);
|
||||
}
|
||||
|
||||
void audio_stream_write_pcm(audio_stream* audio,
|
||||
unsigned char* data, int length) {
|
||||
|
||||
/* Update counter */
|
||||
audio->pcm_bytes_written += length;
|
||||
|
||||
/* Resize audio buffer if necessary */
|
||||
if (length > audio->length) {
|
||||
|
||||
/* Resize to double provided length */
|
||||
audio->length = length*2;
|
||||
audio->pcm_data = realloc(audio->pcm_data, audio->length);
|
||||
|
||||
}
|
||||
|
||||
/* Flush if necessary */
|
||||
if (audio->used + length > audio->length)
|
||||
audio_stream_flush(audio);
|
||||
|
||||
/* Append to buffer */
|
||||
memcpy(&(audio->pcm_data[audio->used]), data, length);
|
||||
audio->used += length;
|
||||
|
||||
}
|
||||
|
||||
void audio_stream_flush(audio_stream* audio) {
|
||||
|
||||
/* If data in buffer */
|
||||
if (audio->used != 0) {
|
||||
|
||||
/* Write data */
|
||||
audio->encoder->write_handler(audio,
|
||||
audio->pcm_data, audio->used);
|
||||
|
||||
/* Reset buffer */
|
||||
audio->used = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void audio_stream_write_encoded(audio_stream* audio,
|
||||
unsigned char* data, int length) {
|
||||
|
||||
/* Resize audio buffer if necessary */
|
||||
if (audio->encoded_data_used + length > audio->encoded_data_length) {
|
||||
|
||||
/* Increase to double concatenated size to accomodate */
|
||||
audio->encoded_data_length = (audio->encoded_data_length + length)*2;
|
||||
audio->encoded_data = realloc(audio->encoded_data,
|
||||
audio->encoded_data_length);
|
||||
|
||||
}
|
||||
|
||||
/* Append to buffer */
|
||||
memcpy(&(audio->encoded_data[audio->encoded_data_used]), data, length);
|
||||
audio->encoded_data_used += length;
|
||||
|
||||
}
|
||||
|
602
protocols/rdp/src/client.c
Normal file
602
protocols/rdp/src/client.c
Normal file
@ -0,0 +1,602 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
* David PHAM-VAN <d.pham-van@ulteo.com> Ulteo SAS - http://www.ulteo.com
|
||||
* Laurent Meunier <laurent@deltalima.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/cache/bitmap.h>
|
||||
#include <freerdp/cache/brush.h>
|
||||
#include <freerdp/cache/glyph.h>
|
||||
#include <freerdp/cache/palette.h>
|
||||
#include <freerdp/cache/pointer.h>
|
||||
#include <freerdp/cache/offscreen.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/input.h>
|
||||
#include <freerdp/constants.h>
|
||||
|
||||
#include <guacamole/socket.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "wav_encoder.h"
|
||||
|
||||
#ifdef ENABLE_OGG
|
||||
#include "ogg_encoder.h"
|
||||
#endif
|
||||
|
||||
#include "client.h"
|
||||
#include "guac_handlers.h"
|
||||
#include "rdp_keymap.h"
|
||||
#include "rdp_bitmap.h"
|
||||
#include "rdp_glyph.h"
|
||||
#include "rdp_pointer.h"
|
||||
#include "rdp_gdi.h"
|
||||
#include "default_pointer.h"
|
||||
|
||||
/* Client plugin arguments */
|
||||
const char* GUAC_CLIENT_ARGS[] = {
|
||||
"hostname",
|
||||
"port",
|
||||
"domain",
|
||||
"username",
|
||||
"password",
|
||||
"width",
|
||||
"height",
|
||||
"initial-program",
|
||||
"color-depth",
|
||||
"disable-audio",
|
||||
"console",
|
||||
"console-audio",
|
||||
"server-layout",
|
||||
NULL
|
||||
};
|
||||
|
||||
enum RDP_ARGS_IDX {
|
||||
|
||||
IDX_HOSTNAME,
|
||||
IDX_PORT,
|
||||
IDX_DOMAIN,
|
||||
IDX_USERNAME,
|
||||
IDX_PASSWORD,
|
||||
IDX_WIDTH,
|
||||
IDX_HEIGHT,
|
||||
IDX_INITIAL_PROGRAM,
|
||||
IDX_COLOR_DEPTH,
|
||||
IDX_DISABLE_AUDIO,
|
||||
IDX_CONSOLE,
|
||||
IDX_CONSOLE_AUDIO,
|
||||
IDX_SERVER_LAYOUT,
|
||||
RDP_ARGS_COUNT
|
||||
};
|
||||
|
||||
int __guac_receive_channel_data(freerdp* rdp_inst, int channelId, uint8* data, int size, int flags, int total_size) {
|
||||
return freerdp_channels_data(rdp_inst, channelId, data, size, flags, total_size);
|
||||
}
|
||||
|
||||
boolean rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
|
||||
rdpContext* context = instance->context;
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdpChannels* channels = context->channels;
|
||||
rdpBitmap* bitmap;
|
||||
rdpGlyph* glyph;
|
||||
rdpPointer* pointer;
|
||||
rdpPrimaryUpdate* primary;
|
||||
CLRCONV* clrconv;
|
||||
int i;
|
||||
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Load clipboard plugin */
|
||||
if (freerdp_channels_load_plugin(channels, instance->settings,
|
||||
"cliprdr", NULL))
|
||||
guac_client_log_error(client, "Failed to load cliprdr plugin.");
|
||||
|
||||
/* If audio enabled, choose an encoder */
|
||||
if (guac_client_data->audio_enabled) {
|
||||
|
||||
/* Choose an encoding */
|
||||
for (i=0; client->info.audio_mimetypes[i] != NULL; i++) {
|
||||
|
||||
const char* mimetype = client->info.audio_mimetypes[i];
|
||||
|
||||
#ifdef ENABLE_OGG
|
||||
/* If Ogg is supported, done. */
|
||||
if (strcmp(mimetype, ogg_encoder->mimetype) == 0) {
|
||||
guac_client_log_info(client, "Loading Ogg Vorbis encoder.");
|
||||
guac_client_data->audio = audio_stream_alloc(client,
|
||||
ogg_encoder);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If wav is supported, done. */
|
||||
if (strcmp(mimetype, wav_encoder->mimetype) == 0) {
|
||||
guac_client_log_info(client, "Loading wav encoder.");
|
||||
guac_client_data->audio = audio_stream_alloc(client,
|
||||
wav_encoder);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If an encoding is available, load the sound plugin */
|
||||
if (guac_client_data->audio != NULL) {
|
||||
|
||||
/* Load sound plugin */
|
||||
if (freerdp_channels_load_plugin(channels, instance->settings,
|
||||
"guac_rdpsnd", guac_client_data->audio))
|
||||
guac_client_log_error(client,
|
||||
"Failed to load guac_rdpsnd plugin.");
|
||||
|
||||
}
|
||||
else
|
||||
guac_client_log_info(client,
|
||||
"No available audio encoding. Sound disabled.");
|
||||
|
||||
} /* end if audio enabled */
|
||||
|
||||
/* Init color conversion structure */
|
||||
clrconv = xnew(CLRCONV);
|
||||
clrconv->alpha = 1;
|
||||
clrconv->invert = 0;
|
||||
clrconv->rgb555 = 0;
|
||||
clrconv->palette = xnew(rdpPalette);
|
||||
((rdp_freerdp_context*) context)->clrconv = clrconv;
|
||||
|
||||
/* Init FreeRDP cache */
|
||||
instance->context->cache = cache_new(instance->settings);
|
||||
|
||||
/* Set up bitmap handling */
|
||||
bitmap = xnew(rdpBitmap);
|
||||
bitmap->size = sizeof(guac_rdp_bitmap);
|
||||
bitmap->New = guac_rdp_bitmap_new;
|
||||
bitmap->Free = guac_rdp_bitmap_free;
|
||||
bitmap->Paint = guac_rdp_bitmap_paint;
|
||||
bitmap->Decompress = guac_rdp_bitmap_decompress;
|
||||
bitmap->SetSurface = guac_rdp_bitmap_setsurface;
|
||||
graphics_register_bitmap(context->graphics, bitmap);
|
||||
xfree(bitmap);
|
||||
|
||||
/* Set up glyph handling */
|
||||
glyph = xnew(rdpGlyph);
|
||||
glyph->size = sizeof(guac_rdp_glyph);
|
||||
glyph->New = guac_rdp_glyph_new;
|
||||
glyph->Free = guac_rdp_glyph_free;
|
||||
glyph->Draw = guac_rdp_glyph_draw;
|
||||
glyph->BeginDraw = guac_rdp_glyph_begindraw;
|
||||
glyph->EndDraw = guac_rdp_glyph_enddraw;
|
||||
graphics_register_glyph(context->graphics, glyph);
|
||||
xfree(glyph);
|
||||
|
||||
/* Set up pointer handling */
|
||||
pointer = xnew(rdpPointer);
|
||||
pointer->size = sizeof(guac_rdp_pointer);
|
||||
pointer->New = guac_rdp_pointer_new;
|
||||
pointer->Free = guac_rdp_pointer_free;
|
||||
pointer->Set = guac_rdp_pointer_set;
|
||||
#ifdef HAVE_RDPPOINTER_SETNULL
|
||||
pointer->SetNull = guac_rdp_pointer_set_null;
|
||||
#endif
|
||||
#ifdef HAVE_RDPPOINTER_SETDEFAULT
|
||||
pointer->SetDefault = guac_rdp_pointer_set_default;
|
||||
#endif
|
||||
graphics_register_pointer(context->graphics, pointer);
|
||||
xfree(pointer);
|
||||
|
||||
/* Set up GDI */
|
||||
instance->update->EndPaint = guac_rdp_gdi_end_paint;
|
||||
instance->update->Palette = guac_rdp_gdi_palette_update;
|
||||
instance->update->SetBounds = guac_rdp_gdi_set_bounds;
|
||||
|
||||
primary = instance->update->primary;
|
||||
primary->DstBlt = guac_rdp_gdi_dstblt;
|
||||
primary->PatBlt = guac_rdp_gdi_patblt;
|
||||
primary->ScrBlt = guac_rdp_gdi_scrblt;
|
||||
primary->MemBlt = guac_rdp_gdi_memblt;
|
||||
primary->OpaqueRect = guac_rdp_gdi_opaquerect;
|
||||
|
||||
pointer_cache_register_callbacks(instance->update);
|
||||
glyph_cache_register_callbacks(instance->update);
|
||||
brush_cache_register_callbacks(instance->update);
|
||||
bitmap_cache_register_callbacks(instance->update);
|
||||
offscreen_cache_register_callbacks(instance->update);
|
||||
palette_cache_register_callbacks(instance->update);
|
||||
|
||||
/* Init channels (pre-connect) */
|
||||
if (freerdp_channels_pre_connect(channels, instance)) {
|
||||
guac_protocol_send_error(client->socket, "Error initializing RDP client channel manager");
|
||||
guac_socket_flush(client->socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
boolean rdp_freerdp_post_connect(freerdp* instance) {
|
||||
|
||||
rdpContext* context = instance->context;
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdpChannels* channels = instance->context->channels;
|
||||
|
||||
/* Init channels (post-connect) */
|
||||
if (freerdp_channels_post_connect(channels, instance)) {
|
||||
guac_protocol_send_error(client->socket, "Error initializing RDP client channel manager");
|
||||
guac_socket_flush(client->socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Client handlers */
|
||||
client->free_handler = rdp_guac_client_free_handler;
|
||||
client->handle_messages = rdp_guac_client_handle_messages;
|
||||
client->mouse_handler = rdp_guac_client_mouse_handler;
|
||||
client->key_handler = rdp_guac_client_key_handler;
|
||||
client->clipboard_handler = rdp_guac_client_clipboard_handler;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void rdp_freerdp_context_new(freerdp* instance, rdpContext* context) {
|
||||
context->channels = freerdp_channels_new();
|
||||
}
|
||||
|
||||
void rdp_freerdp_context_free(freerdp* instance, rdpContext* context) {
|
||||
/* EMPTY */
|
||||
}
|
||||
|
||||
void __guac_rdp_client_load_keymap(guac_client* client,
|
||||
const guac_rdp_keymap* keymap) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Get mapping */
|
||||
const guac_rdp_keysym_desc* mapping = keymap->mapping;
|
||||
|
||||
/* If parent exists, load parent first */
|
||||
if (keymap->parent != NULL)
|
||||
__guac_rdp_client_load_keymap(client, keymap->parent);
|
||||
|
||||
/* Log load */
|
||||
guac_client_log_info(client, "Loading keymap \"%s\"", keymap->name);
|
||||
|
||||
/* Load mapping into keymap */
|
||||
while (mapping->keysym != 0) {
|
||||
|
||||
/* Copy mapping */
|
||||
GUAC_RDP_KEYSYM_LOOKUP(guac_client_data->keymap, mapping->keysym) =
|
||||
*mapping;
|
||||
|
||||
/* Next keysym */
|
||||
mapping++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int guac_client_init(guac_client* client, int argc, char** argv) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data;
|
||||
|
||||
freerdp* rdp_inst;
|
||||
rdpSettings* settings;
|
||||
|
||||
char* hostname;
|
||||
int port = RDP_DEFAULT_PORT;
|
||||
boolean bitmap_cache;
|
||||
|
||||
/**
|
||||
* Selected server-side keymap. Client will be assumed to also use this
|
||||
* keymap. Keys will be sent to server based on client input on a
|
||||
* best-effort basis.
|
||||
*/
|
||||
const guac_rdp_keymap* chosen_keymap;
|
||||
|
||||
if (argc < RDP_ARGS_COUNT) {
|
||||
|
||||
guac_protocol_send_error(client->socket,
|
||||
"Wrong argument count received.");
|
||||
guac_socket_flush(client->socket);
|
||||
|
||||
guac_error = GUAC_STATUS_BAD_ARGUMENT;
|
||||
guac_error_message = "Wrong argument count received";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If port specified, use it */
|
||||
if (argv[IDX_PORT][0] != '\0')
|
||||
port = atoi(argv[IDX_PORT]);
|
||||
|
||||
hostname = argv[IDX_HOSTNAME];
|
||||
|
||||
/* Allocate client data */
|
||||
guac_client_data = malloc(sizeof(rdp_guac_client_data));
|
||||
|
||||
/* Init client */
|
||||
freerdp_channels_global_init();
|
||||
rdp_inst = freerdp_new();
|
||||
rdp_inst->PreConnect = rdp_freerdp_pre_connect;
|
||||
rdp_inst->PostConnect = rdp_freerdp_post_connect;
|
||||
rdp_inst->ReceiveChannelData = __guac_receive_channel_data;
|
||||
|
||||
/* Allocate FreeRDP context */
|
||||
rdp_inst->context_size = sizeof(rdp_freerdp_context);
|
||||
rdp_inst->ContextNew = (pContextNew) rdp_freerdp_context_new;
|
||||
rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free;
|
||||
freerdp_context_new(rdp_inst);
|
||||
|
||||
/* Set settings */
|
||||
settings = rdp_inst->settings;
|
||||
|
||||
/* Console */
|
||||
settings->console_session = (strcmp(argv[IDX_CONSOLE], "true") == 0);
|
||||
settings->console_audio = (strcmp(argv[IDX_CONSOLE_AUDIO], "true") == 0);
|
||||
|
||||
/* --no-auth */
|
||||
settings->authentication = false;
|
||||
|
||||
/* --sec rdp */
|
||||
settings->rdp_security = true;
|
||||
settings->tls_security = false;
|
||||
settings->nla_security = false;
|
||||
settings->encryption = true;
|
||||
settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
|
||||
settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
|
||||
/* Use optimal width unless overridden */
|
||||
settings->width = client->info.optimal_width;
|
||||
if (argv[IDX_WIDTH][0] != '\0')
|
||||
settings->width = atoi(argv[IDX_WIDTH]);
|
||||
|
||||
/* Use default width if given width is invalid. */
|
||||
if (settings->width <= 0) {
|
||||
settings->width = RDP_DEFAULT_WIDTH;
|
||||
guac_client_log_error(client,
|
||||
"Invalid width: \"%s\". Using default of %i.",
|
||||
argv[IDX_WIDTH], settings->width);
|
||||
}
|
||||
|
||||
/* Round width up to nearest multiple of 4 */
|
||||
settings->width = (settings->width + 3) & ~0x3;
|
||||
|
||||
/* Use optimal height unless overridden */
|
||||
settings->height = client->info.optimal_height;
|
||||
if (argv[IDX_HEIGHT][0] != '\0')
|
||||
settings->height = atoi(argv[IDX_HEIGHT]);
|
||||
|
||||
/* Use default height if given height is invalid. */
|
||||
if (settings->height <= 0) {
|
||||
settings->height = RDP_DEFAULT_HEIGHT;
|
||||
guac_client_log_error(client,
|
||||
"Invalid height: \"%s\". Using default of %i.",
|
||||
argv[IDX_WIDTH], settings->height);
|
||||
}
|
||||
|
||||
/* Set hostname */
|
||||
settings->hostname = strdup(hostname);
|
||||
settings->port = port;
|
||||
settings->window_title = strdup(hostname);
|
||||
|
||||
/* Domain */
|
||||
if (argv[IDX_DOMAIN][0] != '\0')
|
||||
settings->domain = strdup(argv[IDX_DOMAIN]);
|
||||
|
||||
/* Username */
|
||||
if (argv[IDX_USERNAME][0] != '\0')
|
||||
settings->username = strdup(argv[IDX_USERNAME]);
|
||||
|
||||
/* Password */
|
||||
if (argv[IDX_PASSWORD][0] != '\0') {
|
||||
settings->password = strdup(argv[IDX_PASSWORD]);
|
||||
settings->autologon = 1;
|
||||
}
|
||||
|
||||
/* Initial program */
|
||||
if (argv[IDX_INITIAL_PROGRAM][0] != '\0')
|
||||
settings->shell = strdup(argv[IDX_INITIAL_PROGRAM]);
|
||||
|
||||
/* Session color depth */
|
||||
settings->color_depth = RDP_DEFAULT_DEPTH;
|
||||
if (argv[IDX_COLOR_DEPTH][0] != '\0')
|
||||
settings->color_depth = atoi(argv[IDX_COLOR_DEPTH]);
|
||||
|
||||
/* Use default depth if given depth is invalid. */
|
||||
if (settings->color_depth == 0) {
|
||||
settings->color_depth = RDP_DEFAULT_DEPTH;
|
||||
guac_client_log_error(client,
|
||||
"Invalid color-depth: \"%s\". Using default of %i.",
|
||||
argv[IDX_WIDTH], settings->color_depth);
|
||||
}
|
||||
|
||||
/* Audio enable/disable */
|
||||
guac_client_data->audio_enabled =
|
||||
(strcmp(argv[IDX_DISABLE_AUDIO], "true") != 0);
|
||||
|
||||
/* Order support */
|
||||
bitmap_cache = settings->bitmap_cache;
|
||||
settings->os_major_type = OSMAJORTYPE_UNSPECIFIED;
|
||||
settings->os_minor_type = OSMINORTYPE_UNSPECIFIED;
|
||||
settings->order_support[NEG_DSTBLT_INDEX] = true;
|
||||
settings->order_support[NEG_PATBLT_INDEX] = false; /* PATBLT not yet supported */
|
||||
settings->order_support[NEG_SCRBLT_INDEX] = true;
|
||||
settings->order_support[NEG_OPAQUE_RECT_INDEX] = true;
|
||||
settings->order_support[NEG_DRAWNINEGRID_INDEX] = false;
|
||||
settings->order_support[NEG_MULTIDSTBLT_INDEX] = false;
|
||||
settings->order_support[NEG_MULTIPATBLT_INDEX] = false;
|
||||
settings->order_support[NEG_MULTISCRBLT_INDEX] = false;
|
||||
settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = false;
|
||||
settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = false;
|
||||
settings->order_support[NEG_LINETO_INDEX] = false;
|
||||
settings->order_support[NEG_POLYLINE_INDEX] = false;
|
||||
settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache;
|
||||
settings->order_support[NEG_MEM3BLT_INDEX] = false;
|
||||
settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
|
||||
settings->order_support[NEG_MEM3BLT_V2_INDEX] = false;
|
||||
settings->order_support[NEG_SAVEBITMAP_INDEX] = false;
|
||||
settings->order_support[NEG_GLYPH_INDEX_INDEX] = true;
|
||||
settings->order_support[NEG_FAST_INDEX_INDEX] = true;
|
||||
settings->order_support[NEG_FAST_GLYPH_INDEX] = true;
|
||||
settings->order_support[NEG_POLYGON_SC_INDEX] = false;
|
||||
settings->order_support[NEG_POLYGON_CB_INDEX] = false;
|
||||
settings->order_support[NEG_ELLIPSE_SC_INDEX] = false;
|
||||
settings->order_support[NEG_ELLIPSE_CB_INDEX] = false;
|
||||
|
||||
/* Store client data */
|
||||
guac_client_data->rdp_inst = rdp_inst;
|
||||
guac_client_data->bounded = false;
|
||||
guac_client_data->mouse_button_mask = 0;
|
||||
guac_client_data->current_surface = GUAC_DEFAULT_LAYER;
|
||||
guac_client_data->clipboard = NULL;
|
||||
guac_client_data->audio = NULL;
|
||||
|
||||
/* Recursive attribute for locks */
|
||||
pthread_mutexattr_init(&(guac_client_data->attributes));
|
||||
pthread_mutexattr_settype(&(guac_client_data->attributes),
|
||||
PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
/* Init update lock */
|
||||
pthread_mutex_init(&(guac_client_data->update_lock),
|
||||
&(guac_client_data->attributes));
|
||||
|
||||
/* Init RDP lock */
|
||||
pthread_mutex_init(&(guac_client_data->rdp_lock),
|
||||
&(guac_client_data->attributes));
|
||||
|
||||
/* Clear keysym state mapping and keymap */
|
||||
memset(guac_client_data->keysym_state, 0,
|
||||
sizeof(guac_rdp_keysym_state_map));
|
||||
|
||||
memset(guac_client_data->keymap, 0,
|
||||
sizeof(guac_rdp_static_keymap));
|
||||
|
||||
client->data = guac_client_data;
|
||||
((rdp_freerdp_context*) rdp_inst->context)->client = client;
|
||||
|
||||
/* Pick keymap based on argument */
|
||||
if (argv[IDX_SERVER_LAYOUT][0] != '\0') {
|
||||
|
||||
/* US English Qwerty */
|
||||
if (strcmp("en-us-qwerty", argv[IDX_SERVER_LAYOUT]) == 0)
|
||||
chosen_keymap = &guac_rdp_keymap_en_us;
|
||||
|
||||
/* German Qwertz */
|
||||
else if (strcmp("de-de-qwertz", argv[IDX_SERVER_LAYOUT]) == 0)
|
||||
chosen_keymap = &guac_rdp_keymap_de_de;
|
||||
|
||||
/* French Azerty */
|
||||
else if (strcmp("fr-fr-azerty", argv[IDX_SERVER_LAYOUT]) == 0)
|
||||
chosen_keymap = &guac_rdp_keymap_fr_fr;
|
||||
|
||||
/* Failsafe (Unicode) keymap */
|
||||
else if (strcmp("failsafe", argv[IDX_SERVER_LAYOUT]) == 0)
|
||||
chosen_keymap = &guac_rdp_keymap_failsafe;
|
||||
|
||||
/* If keymap unknown, resort to failsafe */
|
||||
else {
|
||||
|
||||
guac_client_log_error(client,
|
||||
"Unknown layout \"%s\". Using the failsafe layout instead.",
|
||||
argv[IDX_SERVER_LAYOUT]);
|
||||
|
||||
chosen_keymap = &guac_rdp_keymap_failsafe;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If no keymap requested, assume US */
|
||||
else
|
||||
chosen_keymap = &guac_rdp_keymap_en_us;
|
||||
|
||||
/* Load keymap into client */
|
||||
__guac_rdp_client_load_keymap(client, chosen_keymap);
|
||||
|
||||
/* Set server-side keymap */
|
||||
settings->kbd_layout = chosen_keymap->freerdp_keyboard_layout;
|
||||
|
||||
/* Connect to RDP server */
|
||||
if (!freerdp_connect(rdp_inst)) {
|
||||
|
||||
guac_protocol_send_error(client->socket,
|
||||
"Error connecting to RDP server");
|
||||
guac_socket_flush(client->socket);
|
||||
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "Error connecting to RDP server";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send connection name */
|
||||
guac_protocol_send_name(client->socket, settings->window_title);
|
||||
|
||||
/* Send size */
|
||||
guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER,
|
||||
settings->width, settings->height);
|
||||
|
||||
/* Create glyph surfaces */
|
||||
guac_client_data->opaque_glyph_surface = cairo_image_surface_create(
|
||||
CAIRO_FORMAT_RGB24, settings->width, settings->height);
|
||||
|
||||
guac_client_data->trans_glyph_surface = cairo_image_surface_create(
|
||||
CAIRO_FORMAT_ARGB32, settings->width, settings->height);
|
||||
|
||||
/* Set default pointer */
|
||||
guac_rdp_set_default_pointer(client);
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
106
protocols/rdp/src/default_pointer.c
Normal file
106
protocols/rdp/src/default_pointer.c
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
/* Macros for prettying up the embedded image. */
|
||||
#define X 0x00,0x00,0x00,0xFF
|
||||
#define O 0xFF,0xFF,0xFF,0xFF
|
||||
#define _ 0x00,0x00,0x00,0x00
|
||||
|
||||
/* Dimensions */
|
||||
const int guac_rdp_default_pointer_width = 11;
|
||||
const int guac_rdp_default_pointer_height = 16;
|
||||
|
||||
/* Format */
|
||||
const cairo_format_t guac_rdp_default_pointer_format = CAIRO_FORMAT_ARGB32;
|
||||
const int guac_rdp_default_pointer_stride = 44;
|
||||
|
||||
/* Embedded pointer graphic */
|
||||
unsigned char guac_rdp_default_pointer[] = {
|
||||
|
||||
O,_,_,_,_,_,_,_,_,_,_,
|
||||
O,O,_,_,_,_,_,_,_,_,_,
|
||||
O,X,O,_,_,_,_,_,_,_,_,
|
||||
O,X,X,O,_,_,_,_,_,_,_,
|
||||
O,X,X,X,O,_,_,_,_,_,_,
|
||||
O,X,X,X,X,O,_,_,_,_,_,
|
||||
O,X,X,X,X,X,O,_,_,_,_,
|
||||
O,X,X,X,X,X,X,O,_,_,_,
|
||||
O,X,X,X,X,X,X,X,O,_,_,
|
||||
O,X,X,X,X,X,X,X,X,O,_,
|
||||
O,X,X,X,X,X,O,O,O,O,O,
|
||||
O,X,X,O,X,X,O,_,_,_,_,
|
||||
O,X,O,_,O,X,X,O,_,_,_,
|
||||
O,O,_,_,O,X,X,O,_,_,_,
|
||||
O,_,_,_,_,O,X,X,O,_,_,
|
||||
_,_,_,_,_,O,O,O,O,_,_
|
||||
|
||||
};
|
||||
|
||||
|
||||
void guac_rdp_set_default_pointer(guac_client* client) {
|
||||
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
/* Draw to buffer */
|
||||
guac_layer* cursor = guac_client_alloc_buffer(client);
|
||||
|
||||
cairo_surface_t* graphic = cairo_image_surface_create_for_data(
|
||||
guac_rdp_default_pointer,
|
||||
guac_rdp_default_pointer_format,
|
||||
guac_rdp_default_pointer_width,
|
||||
guac_rdp_default_pointer_height,
|
||||
guac_rdp_default_pointer_stride);
|
||||
|
||||
guac_protocol_send_png(socket, GUAC_COMP_SRC, cursor, 0, 0, graphic);
|
||||
cairo_surface_destroy(graphic);
|
||||
|
||||
/* Set cursor */
|
||||
guac_protocol_send_cursor(socket, 0, 0, cursor,
|
||||
0, 0,
|
||||
guac_rdp_default_pointer_width,
|
||||
guac_rdp_default_pointer_height);
|
||||
|
||||
/* Free buffer */
|
||||
guac_client_free_buffer(client, cursor);
|
||||
|
||||
}
|
||||
|
439
protocols/rdp/src/guac_handlers.c
Normal file
439
protocols/rdp/src/guac_handlers.c
Normal file
@ -0,0 +1,439 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
* Jocelyn DELALANDE <j.delalande@ulteo.com> Ulteo SAS - http://www.ulteo.com
|
||||
*
|
||||
* Portions created by Ulteo SAS employees are Copyright (C) 2012 Ulteo SAS
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/input.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/cache/cache.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/plugins/cliprdr.h>
|
||||
|
||||
#include <guacamole/socket.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_keymap.h"
|
||||
#include "rdp_cliprdr.h"
|
||||
#include "guac_handlers.h"
|
||||
|
||||
void __guac_rdp_update_keysyms(guac_client* client, const int* keysym_string, int from, int to);
|
||||
int __guac_rdp_send_keysym(guac_client* client, int keysym, int pressed);
|
||||
|
||||
|
||||
int rdp_guac_client_free_handler(guac_client* client) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) client->data;
|
||||
|
||||
freerdp* rdp_inst = guac_client_data->rdp_inst;
|
||||
rdpChannels* channels = rdp_inst->context->channels;
|
||||
|
||||
/* Clean up RDP client */
|
||||
freerdp_channels_close(channels, rdp_inst);
|
||||
freerdp_channels_free(channels);
|
||||
freerdp_disconnect(rdp_inst);
|
||||
freerdp_clrconv_free(((rdp_freerdp_context*) rdp_inst->context)->clrconv);
|
||||
cache_free(rdp_inst->context->cache);
|
||||
freerdp_free(rdp_inst);
|
||||
|
||||
/* Free client data */
|
||||
cairo_surface_destroy(guac_client_data->opaque_glyph_surface);
|
||||
cairo_surface_destroy(guac_client_data->trans_glyph_surface);
|
||||
free(guac_client_data->clipboard);
|
||||
free(guac_client_data);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int rdp_guac_client_handle_messages(guac_client* client) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
freerdp* rdp_inst = guac_client_data->rdp_inst;
|
||||
rdpChannels* channels = rdp_inst->context->channels;
|
||||
|
||||
int index;
|
||||
int max_fd, fd;
|
||||
void* read_fds[32];
|
||||
void* write_fds[32];
|
||||
int read_count = 0;
|
||||
int write_count = 0;
|
||||
fd_set rfds, wfds;
|
||||
RDP_EVENT* event;
|
||||
|
||||
struct timeval timeout = {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = 250000
|
||||
};
|
||||
|
||||
/* get rdp fds */
|
||||
if (!freerdp_get_fds(rdp_inst, read_fds, &read_count, write_fds, &write_count)) {
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "Unable to read RDP file descriptors";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get channel fds */
|
||||
if (!freerdp_channels_get_fds(channels, rdp_inst, read_fds, &read_count, write_fds, &write_count)) {
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "Unable to read RDP channel file descriptors";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Construct read fd_set */
|
||||
max_fd = 0;
|
||||
FD_ZERO(&rfds);
|
||||
for (index = 0; index < read_count; index++) {
|
||||
fd = (int)(long) (read_fds[index]);
|
||||
if (fd > max_fd)
|
||||
max_fd = fd;
|
||||
FD_SET(fd, &rfds);
|
||||
}
|
||||
|
||||
/* Construct write fd_set */
|
||||
FD_ZERO(&wfds);
|
||||
for (index = 0; index < write_count; index++) {
|
||||
fd = (int)(long) (write_fds[index]);
|
||||
if (fd > max_fd)
|
||||
max_fd = fd;
|
||||
FD_SET(fd, &wfds);
|
||||
}
|
||||
|
||||
/* If no file descriptors, error */
|
||||
if (max_fd == 0) {
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "No file descriptors";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Otherwise, wait for file descriptors given */
|
||||
if (select(max_fd + 1, &rfds, &wfds, NULL, &timeout) == -1) {
|
||||
/* these are not really errors */
|
||||
if (!((errno == EAGAIN) ||
|
||||
(errno == EWOULDBLOCK) ||
|
||||
(errno == EINPROGRESS) ||
|
||||
(errno == EINTR))) /* signal occurred */
|
||||
{
|
||||
guac_error = GUAC_STATUS_SEE_ERRNO;
|
||||
guac_error_message = "Error waiting for file descriptor";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
|
||||
/* Check the libfreerdp fds */
|
||||
if (!freerdp_check_fds(rdp_inst)) {
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "Error handling RDP file descriptors";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check channel fds */
|
||||
if (!freerdp_channels_check_fds(channels, rdp_inst)) {
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "Error handling RDP channel file descriptors";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check for channel events */
|
||||
event = freerdp_channels_pop_event(channels);
|
||||
if (event) {
|
||||
|
||||
/* Handle clipboard events */
|
||||
if (event->event_class == RDP_EVENT_CLASS_CLIPRDR)
|
||||
guac_rdp_process_cliprdr_event(client, event);
|
||||
|
||||
freerdp_event_free(event);
|
||||
|
||||
}
|
||||
|
||||
/* Handle RDP disconnect */
|
||||
if (freerdp_shall_disconnect(rdp_inst)) {
|
||||
guac_error = GUAC_STATUS_NO_INPUT;
|
||||
guac_error_message = "RDP server closed connection";
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
/* Flush any audio */
|
||||
if (guac_client_data->audio != NULL) {
|
||||
pthread_mutex_lock(&(guac_client_data->update_lock));
|
||||
guac_socket_flush(guac_client_data->audio->stream->socket);
|
||||
pthread_mutex_unlock(&(guac_client_data->update_lock));
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int rdp_guac_client_mouse_handler(guac_client* client, int x, int y, int mask) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
freerdp* rdp_inst = guac_client_data->rdp_inst;
|
||||
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
|
||||
/* If button mask unchanged, just send move event */
|
||||
if (mask == guac_client_data->mouse_button_mask)
|
||||
rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_MOVE, x, y);
|
||||
|
||||
/* Otherwise, send events describing button change */
|
||||
else {
|
||||
|
||||
/* Mouse buttons which have JUST become released */
|
||||
int released_mask = guac_client_data->mouse_button_mask & ~mask;
|
||||
|
||||
/* Mouse buttons which have JUST become pressed */
|
||||
int pressed_mask = ~guac_client_data->mouse_button_mask & mask;
|
||||
|
||||
/* Release event */
|
||||
if (released_mask & 0x07) {
|
||||
|
||||
/* Calculate flags */
|
||||
int flags = 0;
|
||||
if (released_mask & 0x01) flags |= PTR_FLAGS_BUTTON1;
|
||||
if (released_mask & 0x02) flags |= PTR_FLAGS_BUTTON3;
|
||||
if (released_mask & 0x04) flags |= PTR_FLAGS_BUTTON2;
|
||||
|
||||
rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
|
||||
|
||||
}
|
||||
|
||||
/* Press event */
|
||||
if (pressed_mask & 0x07) {
|
||||
|
||||
/* Calculate flags */
|
||||
int flags = PTR_FLAGS_DOWN;
|
||||
if (pressed_mask & 0x01) flags |= PTR_FLAGS_BUTTON1;
|
||||
if (pressed_mask & 0x02) flags |= PTR_FLAGS_BUTTON3;
|
||||
if (pressed_mask & 0x04) flags |= PTR_FLAGS_BUTTON2;
|
||||
if (pressed_mask & 0x08) flags |= PTR_FLAGS_WHEEL | 0x78;
|
||||
if (pressed_mask & 0x10) flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88;
|
||||
|
||||
/* Send event */
|
||||
rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
|
||||
|
||||
}
|
||||
|
||||
/* Scroll event */
|
||||
if (pressed_mask & 0x18) {
|
||||
|
||||
/* Down */
|
||||
if (pressed_mask & 0x08)
|
||||
rdp_inst->input->MouseEvent(
|
||||
rdp_inst->input,
|
||||
PTR_FLAGS_WHEEL | 0x78,
|
||||
x, y);
|
||||
|
||||
/* Up */
|
||||
if (pressed_mask & 0x10)
|
||||
rdp_inst->input->MouseEvent(
|
||||
rdp_inst->input,
|
||||
PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88,
|
||||
x, y);
|
||||
|
||||
}
|
||||
|
||||
|
||||
guac_client_data->mouse_button_mask = mask;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int __guac_rdp_send_keysym(guac_client* client, int keysym, int pressed) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
freerdp* rdp_inst = guac_client_data->rdp_inst;
|
||||
|
||||
/* If keysym can be in lookup table */
|
||||
if (GUAC_RDP_KEYSYM_STORABLE(keysym)) {
|
||||
|
||||
/* Look up scancode mapping */
|
||||
const guac_rdp_keysym_desc* keysym_desc =
|
||||
&GUAC_RDP_KEYSYM_LOOKUP(guac_client_data->keymap, keysym);
|
||||
|
||||
/* If defined, send event */
|
||||
if (keysym_desc->scancode != 0) {
|
||||
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
|
||||
/* If defined, send any prerequesite keys that must be set */
|
||||
if (keysym_desc->set_keysyms != NULL)
|
||||
__guac_rdp_update_keysyms(client, keysym_desc->set_keysyms, 0, 1);
|
||||
|
||||
/* If defined, release any keys that must be cleared */
|
||||
if (keysym_desc->clear_keysyms != NULL)
|
||||
__guac_rdp_update_keysyms(client, keysym_desc->clear_keysyms, 1, 0);
|
||||
|
||||
/* Send actual key */
|
||||
rdp_inst->input->KeyboardEvent(
|
||||
rdp_inst->input,
|
||||
keysym_desc->flags
|
||||
| (pressed ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE),
|
||||
keysym_desc->scancode);
|
||||
|
||||
/* If defined, release any keys that were originally released */
|
||||
if (keysym_desc->set_keysyms != NULL)
|
||||
__guac_rdp_update_keysyms(client, keysym_desc->set_keysyms, 0, 0);
|
||||
|
||||
/* If defined, send any keys that were originally set */
|
||||
if (keysym_desc->clear_keysyms != NULL)
|
||||
__guac_rdp_update_keysyms(client, keysym_desc->clear_keysyms, 1, 1);
|
||||
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall back to unicode events if undefined inside current keymap */
|
||||
|
||||
/* Only send when key pressed - Unicode events do not have
|
||||
* DOWN/RELEASE flags */
|
||||
if (pressed) {
|
||||
|
||||
/* Translate keysym into codepoint */
|
||||
int codepoint;
|
||||
if (keysym <= 0xFF)
|
||||
codepoint = keysym;
|
||||
else if (keysym >= 0x1000000)
|
||||
codepoint = keysym & 0xFFFFFF;
|
||||
else {
|
||||
guac_client_log_info(client,
|
||||
"Unmapped keysym has no equivalent unicode "
|
||||
"value: 0x%x", keysym);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&(guac_client_data->rdp_lock));
|
||||
|
||||
/* Send Unicode event */
|
||||
rdp_inst->input->UnicodeKeyboardEvent(
|
||||
rdp_inst->input,
|
||||
0, codepoint);
|
||||
|
||||
pthread_mutex_unlock(&(guac_client_data->rdp_lock));
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __guac_rdp_update_keysyms(guac_client* client, const int* keysym_string, int from, int to) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
int keysym;
|
||||
|
||||
/* Send all keysyms in string, NULL terminated */
|
||||
while ((keysym = *keysym_string) != 0) {
|
||||
|
||||
/* Get current keysym state */
|
||||
int current_state = GUAC_RDP_KEYSYM_LOOKUP(guac_client_data->keysym_state, keysym);
|
||||
|
||||
/* If key is currently in given state, send event for changing it to specified "to" state */
|
||||
if (current_state == from)
|
||||
__guac_rdp_send_keysym(client, *keysym_string, to);
|
||||
|
||||
/* Next keysym */
|
||||
keysym_string++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int rdp_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
|
||||
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Update keysym state */
|
||||
if (GUAC_RDP_KEYSYM_STORABLE(keysym))
|
||||
GUAC_RDP_KEYSYM_LOOKUP(guac_client_data->keysym_state, keysym) = pressed;
|
||||
|
||||
return __guac_rdp_send_keysym(client, keysym, pressed);
|
||||
|
||||
}
|
||||
|
||||
int rdp_guac_client_clipboard_handler(guac_client* client, char* data) {
|
||||
|
||||
rdpChannels* channels =
|
||||
((rdp_guac_client_data*) client->data)->rdp_inst->context->channels;
|
||||
|
||||
RDP_CB_FORMAT_LIST_EVENT* format_list =
|
||||
(RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(
|
||||
RDP_EVENT_CLASS_CLIPRDR,
|
||||
RDP_EVENT_TYPE_CB_FORMAT_LIST,
|
||||
NULL, NULL);
|
||||
|
||||
/* Free existing data */
|
||||
free(((rdp_guac_client_data*) client->data)->clipboard);
|
||||
|
||||
/* Store data in client */
|
||||
((rdp_guac_client_data*) client->data)->clipboard = strdup(data);
|
||||
|
||||
/* Notify server that text data is now available */
|
||||
format_list->formats = (uint32*) malloc(sizeof(uint32));
|
||||
format_list->formats[0] = CB_FORMAT_TEXT;
|
||||
format_list->num_formats = 1;
|
||||
|
||||
freerdp_channels_send_event(channels, (RDP_EVENT*) format_list);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
211
protocols/rdp/src/ogg_encoder.c
Normal file
211
protocols/rdp/src/ogg_encoder.c
Normal file
@ -0,0 +1,211 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
#include <vorbis/vorbisenc.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "ogg_encoder.h"
|
||||
|
||||
void ogg_encoder_begin_handler(audio_stream* audio) {
|
||||
|
||||
/* Allocate stream state */
|
||||
ogg_encoder_state* state = (ogg_encoder_state*)
|
||||
malloc(sizeof(ogg_encoder_state));
|
||||
|
||||
/* Init state */
|
||||
vorbis_info_init(&(state->info));
|
||||
vorbis_encode_init_vbr(&(state->info), audio->channels, audio->rate, 0.4);
|
||||
|
||||
vorbis_analysis_init(&(state->vorbis_state), &(state->info));
|
||||
vorbis_block_init(&(state->vorbis_state), &(state->vorbis_block));
|
||||
|
||||
vorbis_comment_init(&(state->comment));
|
||||
vorbis_comment_add_tag(&(state->comment), "ENCODER", "libguac-client-rdp");
|
||||
|
||||
ogg_stream_init(&(state->ogg_state), rand());
|
||||
|
||||
/* Write headers */
|
||||
{
|
||||
ogg_packet header;
|
||||
ogg_packet header_comm;
|
||||
ogg_packet header_code;
|
||||
|
||||
vorbis_analysis_headerout(
|
||||
&(state->vorbis_state),
|
||||
&(state->comment),
|
||||
&header, &header_comm, &header_code);
|
||||
|
||||
ogg_stream_packetin(&(state->ogg_state), &header);
|
||||
ogg_stream_packetin(&(state->ogg_state), &header_comm);
|
||||
ogg_stream_packetin(&(state->ogg_state), &header_code);
|
||||
|
||||
/* For each packet */
|
||||
while (ogg_stream_flush(&(state->ogg_state), &(state->ogg_page)) != 0) {
|
||||
|
||||
/* Write packet header */
|
||||
audio_stream_write_encoded(audio,
|
||||
state->ogg_page.header,
|
||||
state->ogg_page.header_len);
|
||||
|
||||
/* Write packet body */
|
||||
audio_stream_write_encoded(audio,
|
||||
state->ogg_page.body,
|
||||
state->ogg_page.body_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
audio->data = state;
|
||||
|
||||
}
|
||||
|
||||
void ogg_encoder_write_blocks(audio_stream* audio) {
|
||||
|
||||
/* Get state */
|
||||
ogg_encoder_state* state = (ogg_encoder_state*) audio->data;
|
||||
|
||||
while (vorbis_analysis_blockout(&(state->vorbis_state),
|
||||
&(state->vorbis_block)) == 1) {
|
||||
|
||||
/* Analyze */
|
||||
vorbis_analysis(&(state->vorbis_block), NULL);
|
||||
vorbis_bitrate_addblock(&(state->vorbis_block));
|
||||
|
||||
/* Flush Ogg pages */
|
||||
while (vorbis_bitrate_flushpacket(&(state->vorbis_state),
|
||||
&(state->ogg_packet))) {
|
||||
|
||||
/* Weld packet into bitstream */
|
||||
ogg_stream_packetin(&(state->ogg_state), &(state->ogg_packet));
|
||||
|
||||
/* Write out pages */
|
||||
while (ogg_stream_pageout(&(state->ogg_state),
|
||||
&(state->ogg_page)) != 0) {
|
||||
|
||||
/* Write packet header */
|
||||
audio_stream_write_encoded(audio,
|
||||
state->ogg_page.header,
|
||||
state->ogg_page.header_len);
|
||||
|
||||
/* Write packet body */
|
||||
audio_stream_write_encoded(audio,
|
||||
state->ogg_page.body,
|
||||
state->ogg_page.body_len);
|
||||
|
||||
if (ogg_page_eos(&(state->ogg_page)))
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ogg_encoder_end_handler(audio_stream* audio) {
|
||||
|
||||
/* Get state */
|
||||
ogg_encoder_state* state = (ogg_encoder_state*) audio->data;
|
||||
|
||||
/* Write end-of-stream */
|
||||
vorbis_analysis_wrote(&(state->vorbis_state), 0);
|
||||
ogg_encoder_write_blocks(audio);
|
||||
|
||||
/* Clean up encoder */
|
||||
ogg_stream_clear(&(state->ogg_state));
|
||||
vorbis_block_clear(&(state->vorbis_block));
|
||||
vorbis_dsp_clear(&(state->vorbis_state));
|
||||
vorbis_comment_clear(&(state->comment));
|
||||
vorbis_info_clear(&(state->info));
|
||||
|
||||
/* Free stream state */
|
||||
free(audio->data);
|
||||
|
||||
}
|
||||
|
||||
void ogg_encoder_write_handler(audio_stream* audio,
|
||||
unsigned char* pcm_data, int length) {
|
||||
|
||||
/* Get state */
|
||||
ogg_encoder_state* state = (ogg_encoder_state*) audio->data;
|
||||
|
||||
/* Calculate samples */
|
||||
int samples = length / audio->channels * 8 / audio->bps;
|
||||
int i;
|
||||
|
||||
/* Get buffer */
|
||||
float** buffer = vorbis_analysis_buffer(&(state->vorbis_state), samples);
|
||||
|
||||
signed char* readbuffer = (signed char*) pcm_data;
|
||||
|
||||
for (i=0; i<samples; i++) {
|
||||
|
||||
/* FIXME: For now, assume 2 channels, 16-bit */
|
||||
int left = ((readbuffer[i*4+1]<<8)|(0x00ff&(int)readbuffer[i*4]));
|
||||
int right = ((readbuffer[i*4+3]<<8)|(0x00ff&(int)readbuffer[i*4+2]));
|
||||
|
||||
/* Store sample in buffer */
|
||||
buffer[0][i] = left / 32768.f;
|
||||
buffer[1][i] = right / 32768.f;
|
||||
|
||||
}
|
||||
|
||||
/* Submit data */
|
||||
vorbis_analysis_wrote(&(state->vorbis_state), samples);
|
||||
|
||||
/* Write data */
|
||||
ogg_encoder_write_blocks(audio);
|
||||
|
||||
}
|
||||
|
||||
/* Encoder handlers */
|
||||
audio_encoder _ogg_encoder = {
|
||||
.mimetype = "audio/ogg",
|
||||
.begin_handler = ogg_encoder_begin_handler,
|
||||
.write_handler = ogg_encoder_write_handler,
|
||||
.end_handler = ogg_encoder_end_handler
|
||||
};
|
||||
|
||||
/* Actual encoder */
|
||||
audio_encoder* ogg_encoder = &_ogg_encoder;
|
||||
|
216
protocols/rdp/src/rdp_bitmap.c
Normal file
216
protocols/rdp/src/rdp_bitmap.c
Normal file
@ -0,0 +1,216 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include <guacamole/socket.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_bitmap.h"
|
||||
|
||||
void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
/* Allocate buffer */
|
||||
guac_layer* buffer = guac_client_alloc_buffer(client);
|
||||
|
||||
/* Cache image data if present */
|
||||
if (bitmap->data != NULL) {
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
bitmap->data, CAIRO_FORMAT_RGB24,
|
||||
bitmap->width, bitmap->height, 4*bitmap->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket,
|
||||
GUAC_COMP_SRC, buffer, 0, 0, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
}
|
||||
|
||||
/* Store buffer reference in bitmap */
|
||||
((guac_rdp_bitmap*) bitmap)->layer = buffer;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
||||
|
||||
/* Convert image data if present */
|
||||
if (bitmap->data != NULL) {
|
||||
|
||||
/* Convert image data to 32-bit RGB */
|
||||
unsigned char* image_buffer = freerdp_image_convert(bitmap->data, NULL,
|
||||
bitmap->width, bitmap->height,
|
||||
context->instance->settings->color_depth,
|
||||
32, ((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
/* Free existing image, if any */
|
||||
if (image_buffer != bitmap->data)
|
||||
free(bitmap->data);
|
||||
|
||||
/* Store converted image in bitmap */
|
||||
bitmap->data = image_buffer;
|
||||
|
||||
}
|
||||
|
||||
/* No corresponding layer yet - caching is deferred. */
|
||||
((guac_rdp_bitmap*) bitmap)->layer = NULL;
|
||||
|
||||
/* Start at zero usage */
|
||||
((guac_rdp_bitmap*) bitmap)->used = 0;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
int width = bitmap->right - bitmap->left + 1;
|
||||
int height = bitmap->bottom - bitmap->top + 1;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* If not cached, cache if necessary */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer == NULL
|
||||
&& ((guac_rdp_bitmap*) bitmap)->used >= 1)
|
||||
guac_rdp_cache_bitmap(context, bitmap);
|
||||
|
||||
/* If cached, retrieve from cache */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
|
||||
guac_protocol_send_copy(socket,
|
||||
((guac_rdp_bitmap*) bitmap)->layer,
|
||||
0, 0, width, height,
|
||||
GUAC_COMP_OVER,
|
||||
GUAC_DEFAULT_LAYER, bitmap->left, bitmap->top);
|
||||
|
||||
/* Otherwise, draw with stored image data */
|
||||
else if (bitmap->data != NULL) {
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
bitmap->data, CAIRO_FORMAT_RGB24,
|
||||
width, height, 4*bitmap->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket,
|
||||
GUAC_COMP_OVER, GUAC_DEFAULT_LAYER,
|
||||
bitmap->left, bitmap->top, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
}
|
||||
|
||||
/* Increment usage counter */
|
||||
((guac_rdp_bitmap*) bitmap)->used++;
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) {
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
|
||||
/* If cached, free buffer */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
|
||||
guac_client_free_buffer(client, ((guac_rdp_bitmap*) bitmap)->layer);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) {
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
|
||||
if (primary)
|
||||
((rdp_guac_client_data*) client->data)->current_surface
|
||||
= GUAC_DEFAULT_LAYER;
|
||||
|
||||
else {
|
||||
|
||||
/* If not available as a surface, make available. */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer == NULL)
|
||||
guac_rdp_cache_bitmap(context, bitmap);
|
||||
|
||||
((rdp_guac_client_data*) client->data)->current_surface
|
||||
= ((guac_rdp_bitmap*) bitmap)->layer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed) {
|
||||
|
||||
int size = width * height * (bpp + 7) / 8;
|
||||
|
||||
if (bitmap->data == NULL)
|
||||
bitmap->data = (uint8*) xmalloc(size);
|
||||
else
|
||||
bitmap->data = (uint8*) xrealloc(bitmap->data, size);
|
||||
|
||||
if (compressed)
|
||||
bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
||||
else
|
||||
freerdp_image_flip(data, bitmap->data, width, height, bpp);
|
||||
|
||||
bitmap->compressed = false;
|
||||
bitmap->length = size;
|
||||
bitmap->bpp = bpp;
|
||||
|
||||
}
|
||||
|
204
protocols/rdp/src/rdp_cliprdr.c
Normal file
204
protocols/rdp/src/rdp_cliprdr.c
Normal file
@ -0,0 +1,204 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/plugins/cliprdr.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_cliprdr.h"
|
||||
|
||||
void guac_rdp_process_cliprdr_event(guac_client* client, RDP_EVENT* event) {
|
||||
|
||||
switch (event->event_type) {
|
||||
|
||||
case RDP_EVENT_TYPE_CB_MONITOR_READY:
|
||||
guac_rdp_process_cb_monitor_ready(client, event);
|
||||
break;
|
||||
|
||||
case RDP_EVENT_TYPE_CB_FORMAT_LIST:
|
||||
guac_rdp_process_cb_format_list(client,
|
||||
(RDP_CB_FORMAT_LIST_EVENT*) event);
|
||||
break;
|
||||
|
||||
case RDP_EVENT_TYPE_CB_DATA_REQUEST:
|
||||
guac_rdp_process_cb_data_request(client,
|
||||
(RDP_CB_DATA_REQUEST_EVENT*) event);
|
||||
break;
|
||||
|
||||
case RDP_EVENT_TYPE_CB_DATA_RESPONSE:
|
||||
guac_rdp_process_cb_data_response(client,
|
||||
(RDP_CB_DATA_RESPONSE_EVENT*) event);
|
||||
break;
|
||||
|
||||
default:
|
||||
guac_client_log_info(client,
|
||||
"Unknown cliprdr event type: 0x%x",
|
||||
event->event_type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_monitor_ready(guac_client* client, RDP_EVENT* event) {
|
||||
|
||||
rdpChannels* channels =
|
||||
((rdp_guac_client_data*) client->data)->rdp_inst->context->channels;
|
||||
|
||||
RDP_CB_FORMAT_LIST_EVENT* format_list =
|
||||
(RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(
|
||||
RDP_EVENT_CLASS_CLIPRDR,
|
||||
RDP_EVENT_TYPE_CB_FORMAT_LIST,
|
||||
NULL, NULL);
|
||||
|
||||
/* Received notification of clipboard support. */
|
||||
|
||||
/* Respond with supported format list */
|
||||
format_list->formats = (uint32*) malloc(sizeof(uint32));
|
||||
format_list->formats[0] = CB_FORMAT_TEXT;
|
||||
format_list->num_formats = 1;
|
||||
|
||||
freerdp_channels_send_event(channels, (RDP_EVENT*) format_list);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_format_list(guac_client* client,
|
||||
RDP_CB_FORMAT_LIST_EVENT* event) {
|
||||
|
||||
rdpChannels* channels =
|
||||
((rdp_guac_client_data*) client->data)->rdp_inst->context->channels;
|
||||
|
||||
/* Received notification of available data */
|
||||
|
||||
int i;
|
||||
for (i=0; i<event->num_formats; i++) {
|
||||
|
||||
/* If plain text available, request it */
|
||||
if (event->formats[i] == CB_FORMAT_TEXT) {
|
||||
|
||||
/* Create new data request */
|
||||
RDP_CB_DATA_REQUEST_EVENT* data_request =
|
||||
(RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(
|
||||
RDP_EVENT_CLASS_CLIPRDR,
|
||||
RDP_EVENT_TYPE_CB_DATA_REQUEST,
|
||||
NULL, NULL);
|
||||
|
||||
/* We want plain text */
|
||||
data_request->format = CB_FORMAT_TEXT;
|
||||
|
||||
/* Send request */
|
||||
freerdp_channels_send_event(channels, (RDP_EVENT*) data_request);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Otherwise, no supported data available */
|
||||
guac_client_log_info(client, "Ignoring unsupported clipboard data");
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_data_request(guac_client* client,
|
||||
RDP_CB_DATA_REQUEST_EVENT* event) {
|
||||
|
||||
rdpChannels* channels =
|
||||
((rdp_guac_client_data*) client->data)->rdp_inst->context->channels;
|
||||
|
||||
/* If text requested, send clipboard text contents */
|
||||
if (event->format == CB_FORMAT_TEXT) {
|
||||
|
||||
/* Get clipboard data */
|
||||
const char* clipboard =
|
||||
((rdp_guac_client_data*) client->data)->clipboard;
|
||||
|
||||
/* Create new data response */
|
||||
RDP_CB_DATA_RESPONSE_EVENT* data_response =
|
||||
(RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(
|
||||
RDP_EVENT_CLASS_CLIPRDR,
|
||||
RDP_EVENT_TYPE_CB_DATA_RESPONSE,
|
||||
NULL, NULL);
|
||||
|
||||
/* Set data and length */
|
||||
if (clipboard != NULL) {
|
||||
data_response->data = (uint8*) strdup(clipboard);
|
||||
data_response->size = strlen(clipboard) + 1;
|
||||
}
|
||||
else {
|
||||
data_response->data = (uint8*) strdup("");
|
||||
data_response->size = 1;
|
||||
}
|
||||
|
||||
/* Send response */
|
||||
freerdp_channels_send_event(channels, (RDP_EVENT*) data_response);
|
||||
|
||||
}
|
||||
|
||||
/* Otherwise ... failure */
|
||||
else
|
||||
guac_client_log_error(client,
|
||||
"Server requested unsupported clipboard data type");
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_data_response(guac_client* client,
|
||||
RDP_CB_DATA_RESPONSE_EVENT* event) {
|
||||
|
||||
/* Received clipboard data */
|
||||
if (event->data[event->size - 1] == '\0') {
|
||||
|
||||
/* Free existing data */
|
||||
free(((rdp_guac_client_data*) client->data)->clipboard);
|
||||
|
||||
/* Store clipboard data */
|
||||
((rdp_guac_client_data*) client->data)->clipboard =
|
||||
strdup((char*) event->data);
|
||||
|
||||
/* Send clipboard data */
|
||||
guac_protocol_send_clipboard(client->socket, (char*) event->data);
|
||||
|
||||
}
|
||||
else
|
||||
guac_client_log_error(client,
|
||||
"Clipboard data missing null terminator");
|
||||
|
||||
}
|
||||
|
522
protocols/rdp/src/rdp_gdi.c
Normal file
522
protocols/rdp/src/rdp_gdi.c
Normal file
@ -0,0 +1,522 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_bitmap.h"
|
||||
|
||||
static void __guac_rdp_clip_rect(rdp_guac_client_data* data, int* x, int* y, int* w, int* h) {
|
||||
|
||||
if (data->bounded) {
|
||||
|
||||
/* Get rect coordinates */
|
||||
int clipped_left = *x;
|
||||
int clipped_top = *y;
|
||||
int clipped_right = clipped_left + *w - 1;
|
||||
int clipped_bottom = clipped_top + *h - 1;
|
||||
|
||||
/* Clip left */
|
||||
if (clipped_left < data->bounds_left) clipped_left = data->bounds_left;
|
||||
else if (clipped_left > data->bounds_right) clipped_left = data->bounds_right;
|
||||
|
||||
/* Clip right */
|
||||
if (clipped_right < data->bounds_left) clipped_right = data->bounds_left;
|
||||
else if (clipped_right > data->bounds_right) clipped_right = data->bounds_right;
|
||||
|
||||
/* Clip top */
|
||||
if (clipped_top < data->bounds_top) clipped_top = data->bounds_top;
|
||||
else if (clipped_top > data->bounds_bottom) clipped_top = data->bounds_bottom;
|
||||
|
||||
/* Clip bottom */
|
||||
if (clipped_bottom < data->bounds_top) clipped_bottom = data->bounds_top;
|
||||
else if (clipped_bottom > data->bounds_bottom) clipped_bottom = data->bounds_bottom;
|
||||
|
||||
/* Store new rect dimensions */
|
||||
*x = clipped_left;
|
||||
*y = clipped_top;
|
||||
*w = clipped_right - clipped_left + 1;
|
||||
*h = clipped_bottom - clipped_top + 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client,
|
||||
int rop3) {
|
||||
|
||||
/* Translate supported ROP3 opcodes into composite modes */
|
||||
switch (rop3) {
|
||||
|
||||
/* "DSon" !(src | dest) */
|
||||
case 0x11: return GUAC_TRANSFER_BINARY_NOR;
|
||||
|
||||
/* "DSna" !src & dest */
|
||||
case 0x22: return GUAC_TRANSFER_BINARY_NSRC_AND;
|
||||
|
||||
/* "Sn" !src */
|
||||
case 0x33: return GUAC_TRANSFER_BINARY_NSRC;
|
||||
|
||||
/* "SDna" (src & !dest) */
|
||||
case 0x44: return GUAC_TRANSFER_BINARY_NDEST_AND;
|
||||
|
||||
/* "Dn" !dest */
|
||||
case 0x55: return GUAC_TRANSFER_BINARY_NDEST;
|
||||
|
||||
/* "SRCINVERT" (src ^ dest) */
|
||||
case 0x66: return GUAC_TRANSFER_BINARY_XOR;
|
||||
|
||||
/* "DSan" !(src & dest) */
|
||||
case 0x77: return GUAC_TRANSFER_BINARY_NAND;
|
||||
|
||||
/* "SRCAND" (src & dest) */
|
||||
case 0x88: return GUAC_TRANSFER_BINARY_AND;
|
||||
|
||||
/* "DSxn" !(src ^ dest) */
|
||||
case 0x99: return GUAC_TRANSFER_BINARY_XNOR;
|
||||
|
||||
/* "MERGEPAINT" (!src | dest)*/
|
||||
case 0xBB: return GUAC_TRANSFER_BINARY_NSRC_OR;
|
||||
|
||||
/* "SDno" (src | !dest) */
|
||||
case 0xDD: return GUAC_TRANSFER_BINARY_NDEST_OR;
|
||||
|
||||
/* "SRCPAINT" (src | dest) */
|
||||
case 0xEE: return GUAC_TRANSFER_BINARY_OR;
|
||||
|
||||
/* 0x00 = "BLACKNESS" (0) */
|
||||
/* 0xAA = "NOP" (dest) */
|
||||
/* 0xCC = "SRCCOPY" (src) */
|
||||
/* 0xFF = "WHITENESS" (1) */
|
||||
|
||||
}
|
||||
|
||||
/* Log warning if ROP3 opcode not supported */
|
||||
guac_client_log_info (client, "guac_rdp_rop3_transfer_function: "
|
||||
"UNSUPPORTED opcode = 0x%02X", rop3);
|
||||
|
||||
/* Default to BINARY_SRC */
|
||||
return GUAC_TRANSFER_BINARY_SRC;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
int x = dstblt->nLeftRect;
|
||||
int y = dstblt->nTopRect;
|
||||
int w = dstblt->nWidth;
|
||||
int h = dstblt->nHeight;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* Clip operation to bounds */
|
||||
__guac_rdp_clip_rect(data, &x, &y, &w, &h);
|
||||
|
||||
switch (dstblt->bRop) {
|
||||
|
||||
/* Blackness */
|
||||
case 0:
|
||||
|
||||
/* Send black rectangle */
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
0, 0, 0, 255);
|
||||
|
||||
break;
|
||||
|
||||
/* DSTINVERT */
|
||||
case 0x55:
|
||||
|
||||
/* Invert */
|
||||
guac_protocol_send_transfer(client->socket,
|
||||
current_layer, x, y, w, h,
|
||||
GUAC_TRANSFER_BINARY_NDEST,
|
||||
current_layer, x, y);
|
||||
|
||||
break;
|
||||
|
||||
/* NOP */
|
||||
case 0xAA:
|
||||
break;
|
||||
|
||||
/* Whiteness */
|
||||
case 0xFF:
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
0xFF, 0xFF, 0xFF, 0xFF);
|
||||
break;
|
||||
|
||||
/* Unsupported ROP3 */
|
||||
default:
|
||||
guac_client_log_info(client,
|
||||
"guac_rdp_gdi_dstblt(rop3=0x%x)", dstblt->bRop);
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) {
|
||||
|
||||
/*
|
||||
* Note that this is not a full implementation of PATBLT. This is a
|
||||
* fallback implementation which only renders a solid block of background
|
||||
* color using the specified ROP3 operation, ignoring whatever brush
|
||||
* was actually specified.
|
||||
*
|
||||
* As libguac-client-rdp explicitly tells the server not to send PATBLT,
|
||||
* well-behaved RDP servers will not use this operation at all, while
|
||||
* others will at least have a fallback.
|
||||
*/
|
||||
|
||||
/* Get client and current layer */
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
const guac_layer* current_layer =
|
||||
((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
int x = patblt->nLeftRect;
|
||||
int y = patblt->nTopRect;
|
||||
int w = patblt->nWidth;
|
||||
int h = patblt->nHeight;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Layer for actual transfer */
|
||||
guac_layer* buffer;
|
||||
|
||||
/*
|
||||
* Warn that rendering is a fallback, as the server should not be sending
|
||||
* this order.
|
||||
*/
|
||||
guac_client_log_info(client, "Using fallback PATBLT (server is ignoring "
|
||||
"negotiated client capabilities)");
|
||||
|
||||
/* Clip operation to bounds */
|
||||
__guac_rdp_clip_rect(data, &x, &y, &w, &h);
|
||||
|
||||
/* Render rectangle based on ROP */
|
||||
switch (patblt->bRop) {
|
||||
|
||||
/* If blackness, send black rectangle */
|
||||
case 0x00:
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
0x00, 0x00, 0x00, 0xFF);
|
||||
break;
|
||||
|
||||
/* If NOP, do nothing */
|
||||
case 0xAA:
|
||||
break;
|
||||
|
||||
/* If operation is just a copy, send foreground only */
|
||||
case 0xCC:
|
||||
case 0xF0:
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
(patblt->foreColor >> 16) & 0xFF,
|
||||
(patblt->foreColor >> 8 ) & 0xFF,
|
||||
(patblt->foreColor ) & 0xFF,
|
||||
0xFF);
|
||||
break;
|
||||
|
||||
/* If whiteness, send white rectangle */
|
||||
case 0xFF:
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
0xFF, 0xFF, 0xFF, 0xFF);
|
||||
break;
|
||||
|
||||
/* Otherwise, invert entire rect */
|
||||
default:
|
||||
|
||||
/* Allocate buffer for transfer */
|
||||
buffer = guac_client_alloc_buffer(client);
|
||||
|
||||
/* Send rectangle stroke */
|
||||
guac_protocol_send_rect(client->socket, buffer,
|
||||
0, 0, w, h);
|
||||
|
||||
/* Fill rectangle with fore color only */
|
||||
guac_protocol_send_cfill(client->socket, GUAC_COMP_OVER, buffer,
|
||||
0xFF, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
/* Transfer */
|
||||
guac_protocol_send_transfer(client->socket,
|
||||
|
||||
/* ... from buffer */
|
||||
buffer, 0, 0, w, h,
|
||||
|
||||
/* ... inverting */
|
||||
GUAC_TRANSFER_BINARY_XOR,
|
||||
|
||||
/* ... to current layer */
|
||||
current_layer, x, y);
|
||||
|
||||
/* Done with buffer */
|
||||
guac_client_free_buffer(client, buffer);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
int x = scrblt->nLeftRect;
|
||||
int y = scrblt->nTopRect;
|
||||
int w = scrblt->nWidth;
|
||||
int h = scrblt->nHeight;
|
||||
|
||||
int x_src = scrblt->nXSrc;
|
||||
int y_src = scrblt->nYSrc;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* Clip operation to bounds */
|
||||
__guac_rdp_clip_rect(data, &x, &y, &w, &h);
|
||||
|
||||
/* Update source coordinates */
|
||||
x_src += x - scrblt->nLeftRect;
|
||||
y_src += y - scrblt->nTopRect;
|
||||
|
||||
/* Copy screen rect to current surface */
|
||||
guac_protocol_send_copy(client->socket,
|
||||
GUAC_DEFAULT_LAYER, x_src, y_src, w, h,
|
||||
GUAC_COMP_OVER, current_layer, x, y);
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
guac_socket* socket = client->socket;
|
||||
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
|
||||
|
||||
int x = memblt->nLeftRect;
|
||||
int y = memblt->nTopRect;
|
||||
int w = memblt->nWidth;
|
||||
int h = memblt->nHeight;
|
||||
|
||||
int x_src = memblt->nXSrc;
|
||||
int y_src = memblt->nYSrc;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* Clip operation to bounds */
|
||||
__guac_rdp_clip_rect(data, &x, &y, &w, &h);
|
||||
|
||||
/* Update source coordinates */
|
||||
x_src += x - memblt->nLeftRect;
|
||||
y_src += y - memblt->nTopRect;
|
||||
|
||||
switch (memblt->bRop) {
|
||||
|
||||
/* If blackness, send black rectangle */
|
||||
case 0x00:
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
0x00, 0x00, 0x00, 0xFF);
|
||||
break;
|
||||
|
||||
/* If NOP, do nothing */
|
||||
case 0xAA:
|
||||
break;
|
||||
|
||||
/* If operation is just SRC, simply copy */
|
||||
case 0xCC:
|
||||
|
||||
/* If not cached, cache if necessary */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer == NULL
|
||||
&& ((guac_rdp_bitmap*) bitmap)->used >= 1)
|
||||
guac_rdp_cache_bitmap(context, memblt->bitmap);
|
||||
|
||||
/* If not cached, send as PNG */
|
||||
if (bitmap->layer == NULL) {
|
||||
if (memblt->bitmap->data != NULL) {
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
memblt->bitmap->data + 4*(x_src + y_src*memblt->bitmap->width),
|
||||
CAIRO_FORMAT_RGB24, w, h, 4*memblt->bitmap->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
x, y, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, copy */
|
||||
else
|
||||
guac_protocol_send_copy(socket,
|
||||
bitmap->layer, x_src, y_src, w, h,
|
||||
GUAC_COMP_OVER, current_layer, x, y);
|
||||
|
||||
/* Increment usage counter */
|
||||
((guac_rdp_bitmap*) bitmap)->used++;
|
||||
|
||||
break;
|
||||
|
||||
/* If whiteness, send white rectangle */
|
||||
case 0xFF:
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
0xFF, 0xFF, 0xFF, 0xFF);
|
||||
break;
|
||||
|
||||
/* Otherwise, use transfer */
|
||||
default:
|
||||
|
||||
/* If not available as a surface, make available. */
|
||||
if (bitmap->layer == NULL)
|
||||
guac_rdp_cache_bitmap(context, memblt->bitmap);
|
||||
|
||||
guac_protocol_send_transfer(socket,
|
||||
bitmap->layer, x_src, y_src, w, h,
|
||||
guac_rdp_rop3_transfer_function(client, memblt->bRop),
|
||||
current_layer, x, y);
|
||||
|
||||
/* Increment usage counter */
|
||||
((guac_rdp_bitmap*) bitmap)->used++;
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
uint32 color = freerdp_color_convert_var(opaque_rect->color,
|
||||
context->instance->settings->color_depth, 32,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
int x = opaque_rect->nLeftRect;
|
||||
int y = opaque_rect->nTopRect;
|
||||
int w = opaque_rect->nWidth;
|
||||
int h = opaque_rect->nHeight;
|
||||
|
||||
/* Clip operation to bounds */
|
||||
__guac_rdp_clip_rect(data, &x, &y, &w, &h);
|
||||
|
||||
guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
(color >> 16) & 0xFF,
|
||||
(color >> 8 ) & 0xFF,
|
||||
(color ) & 0xFF,
|
||||
255);
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) {
|
||||
|
||||
CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv;
|
||||
clrconv->palette->count = palette->number;
|
||||
clrconv->palette->entries = palette->entries;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
|
||||
/* If no bounds given, clear bounding rect */
|
||||
if (bounds == NULL)
|
||||
data->bounded = false;
|
||||
|
||||
/* Otherwise, set bounding rectangle */
|
||||
else {
|
||||
data->bounded = true;
|
||||
data->bounds_left = bounds->left;
|
||||
data->bounds_top = bounds->top;
|
||||
data->bounds_right = bounds->right;
|
||||
data->bounds_bottom = bounds->bottom;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_end_paint(rdpContext* context) {
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
243
protocols/rdp/src/rdp_glyph.c
Normal file
243
protocols/rdp/src/rdp_glyph.c
Normal file
@ -0,0 +1,243 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_glyph.h"
|
||||
|
||||
void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) {
|
||||
|
||||
int x, y, i;
|
||||
int stride;
|
||||
unsigned char* image_buffer;
|
||||
unsigned char* image_buffer_row;
|
||||
|
||||
unsigned char* data = glyph->aj;
|
||||
int width = glyph->cx;
|
||||
int height = glyph->cy;
|
||||
|
||||
/* Init Cairo buffer */
|
||||
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
||||
image_buffer = malloc(height*stride);
|
||||
image_buffer_row = image_buffer;
|
||||
|
||||
/* Copy image data from image data to buffer */
|
||||
for (y = 0; y<height; y++) {
|
||||
|
||||
unsigned int* image_buffer_current;
|
||||
|
||||
/* Get current buffer row, advance to next */
|
||||
image_buffer_current = (unsigned int*) image_buffer_row;
|
||||
image_buffer_row += stride;
|
||||
|
||||
for (x = 0; x<width;) {
|
||||
|
||||
/* Get byte from image data */
|
||||
unsigned int v = *(data++);
|
||||
|
||||
/* Read bits, write pixels */
|
||||
for (i = 0; i<8 && x<width; i++, x++) {
|
||||
|
||||
/* Output RGB */
|
||||
if (v & 0x80)
|
||||
*(image_buffer_current++) = 0xFF000000;
|
||||
else
|
||||
*(image_buffer_current++) = 0x00000000;
|
||||
|
||||
/* Next bit */
|
||||
v <<= 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Store glyph surface */
|
||||
((guac_rdp_glyph*) glyph)->surface = cairo_image_surface_create_for_data(
|
||||
image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Do not attempt to draw glyphs if glyph drawing is not begun */
|
||||
if (guac_client_data->glyph_cairo == NULL)
|
||||
return;
|
||||
|
||||
/* Use glyph as mask */
|
||||
cairo_mask_surface(
|
||||
guac_client_data->glyph_cairo,
|
||||
((guac_rdp_glyph*) glyph)->surface, x, y);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) {
|
||||
|
||||
unsigned char* image_buffer = cairo_image_surface_get_data(
|
||||
((guac_rdp_glyph*) glyph)->surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(((guac_rdp_glyph*) glyph)->surface);
|
||||
free(image_buffer);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_glyph_begindraw(rdpContext* context,
|
||||
int x, int y, int width, int height, uint32 fgcolor, uint32 bgcolor) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Convert foreground color */
|
||||
fgcolor = freerdp_color_convert_var(fgcolor,
|
||||
context->instance->settings->color_depth, 32,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
/* Fill background with color if specified */
|
||||
if (width != 0 && height != 0) {
|
||||
|
||||
/* Prepare for opaque glyphs */
|
||||
guac_client_data->glyph_surface =
|
||||
guac_client_data->opaque_glyph_surface;
|
||||
|
||||
/* Create cairo instance */
|
||||
guac_client_data->glyph_cairo = cairo_create(
|
||||
guac_client_data->glyph_surface);
|
||||
|
||||
/* Convert background color */
|
||||
bgcolor = freerdp_color_convert_var(bgcolor,
|
||||
context->instance->settings->color_depth, 32,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
/* Fill background */
|
||||
cairo_rectangle(guac_client_data->glyph_cairo,
|
||||
x, y, width, height);
|
||||
|
||||
cairo_set_source_rgb(guac_client_data->glyph_cairo,
|
||||
((bgcolor & 0xFF0000) >> 16) / 255.0,
|
||||
((bgcolor & 0x00FF00) >> 8 ) / 255.0,
|
||||
( bgcolor & 0x0000FF ) / 255.0);
|
||||
|
||||
cairo_fill(guac_client_data->glyph_cairo);
|
||||
|
||||
}
|
||||
|
||||
/* Otherwise, prepare for transparent glyphs */
|
||||
else {
|
||||
|
||||
/* Select transparent glyph surface */
|
||||
guac_client_data->glyph_surface =
|
||||
guac_client_data->trans_glyph_surface;
|
||||
|
||||
guac_client_data->glyph_cairo = cairo_create(
|
||||
guac_client_data->glyph_surface);
|
||||
|
||||
/* Clear surface */
|
||||
cairo_set_operator(guac_client_data->glyph_cairo,
|
||||
CAIRO_OPERATOR_SOURCE);
|
||||
|
||||
cairo_set_source_rgba(guac_client_data->glyph_cairo, 0, 0, 0, 0);
|
||||
cairo_paint(guac_client_data->glyph_cairo);
|
||||
|
||||
/* Restore operator */
|
||||
cairo_set_operator(guac_client_data->glyph_cairo,
|
||||
CAIRO_OPERATOR_OVER);
|
||||
|
||||
}
|
||||
|
||||
/* Prepare for glyph drawing */
|
||||
cairo_set_source_rgb(guac_client_data->glyph_cairo,
|
||||
((fgcolor & 0xFF0000) >> 16) / 255.0,
|
||||
((fgcolor & 0x00FF00) >> 8 ) / 255.0,
|
||||
( fgcolor & 0x0000FF ) / 255.0);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_glyph_enddraw(rdpContext* context,
|
||||
int x, int y, int width, int height, uint32 fgcolor, uint32 bgcolor) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
pthread_mutex_lock(&(guac_client_data->update_lock));
|
||||
|
||||
/* Use glyph surface to provide image data for glyph rectangle */
|
||||
cairo_surface_t* glyph_surface = guac_client_data->glyph_surface;
|
||||
int stride = cairo_image_surface_get_stride(glyph_surface);
|
||||
|
||||
/* Calculate bounds */
|
||||
int max_width = cairo_image_surface_get_width(glyph_surface) - x;
|
||||
int max_height = cairo_image_surface_get_height(glyph_surface) - y;
|
||||
|
||||
/* Ensure dimensions of glyph do not exceed bounds */
|
||||
if (width > max_width) width = max_width;
|
||||
if (height > max_height) height = max_height;
|
||||
|
||||
/* Ensure data is ready */
|
||||
cairo_surface_flush(glyph_surface);
|
||||
|
||||
/* Create surface for subsection with text */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
cairo_image_surface_get_data(glyph_surface) + 4*x + y*stride,
|
||||
cairo_image_surface_get_format(glyph_surface),
|
||||
width, height, stride);
|
||||
|
||||
/* Send surface with all glyphs to layer */
|
||||
guac_protocol_send_png(client->socket,
|
||||
GUAC_COMP_OVER, current_layer, x, y,
|
||||
surface);
|
||||
|
||||
/* Destroy surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
/* Destroy cairo instance */
|
||||
cairo_destroy(guac_client_data->glyph_cairo);
|
||||
|
||||
pthread_mutex_unlock(&(guac_client_data->update_lock));
|
||||
}
|
||||
|
61
protocols/rdp/src/rdp_keymap.c
Normal file
61
protocols/rdp/src/rdp_keymap.c
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
const int GUAC_KEYSYMS_SHIFT[] = {0xFFE1, 0};
|
||||
const int GUAC_KEYSYMS_ALL_SHIFT[] = {0xFFE1, 0xFFE2, 0};
|
||||
|
||||
const int GUAC_KEYSYMS_ALTGR[] = {0xFFEA, 0};
|
||||
const int GUAC_KEYSYMS_SHIFT_ALTGR[] = {0xFFE1, 0xFFEA, 0};
|
||||
const int GUAC_KEYSYMS_ALL_SHIFT_ALTGR[] = {0xFFE1, 0xFFE2, 0xFFEA, 0};
|
||||
|
||||
const int GUAC_KEYSYMS_CTRL[] = {0xFFE3, 0};
|
||||
const int GUAC_KEYSYMS_ALL_CTRL[] = {0xFFE3, 0xFFE4, 0};
|
||||
|
||||
const int GUAC_KEYSYMS_ALT[] = {0xFFE9, 0};
|
||||
const int GUAC_KEYSYMS_ALL_ALT[] = {0xFFE9, 0xFFEA, 0};
|
||||
|
||||
const int GUAC_KEYSYMS_CTRL_ALT[] = {0xFFE3, 0xFFE9, 0};
|
||||
|
||||
const int GUAC_KEYSYMS_ALL_MODIFIERS[] = {
|
||||
0xFFE1, 0xFFE2, /* Left and right shift */
|
||||
0xFFE3, 0xFFE4, /* Left and right control */
|
||||
0xFFE9, 0xFFEA, /* Left and right alt (AltGr) */
|
||||
0
|
||||
};
|
||||
|
220
protocols/rdp/src/rdp_keymap_base.c
Normal file
220
protocols/rdp/src/rdp_keymap_base.c
Normal file
@ -0,0 +1,220 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <freerdp/input.h>
|
||||
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
static guac_rdp_keysym_desc __guac_rdp_keymap_mapping[] = {
|
||||
|
||||
/* BackSpace */
|
||||
{ .keysym = 0xff08, .scancode = 0x0E },
|
||||
|
||||
/* Tab */
|
||||
{ .keysym = 0xff09, .scancode = 0x0F },
|
||||
|
||||
/* Return */
|
||||
{ .keysym = 0xff0d, .scancode = 0x1C },
|
||||
|
||||
/* Scroll_Lock */
|
||||
{ .keysym = 0xff14, .scancode = 0x46 },
|
||||
|
||||
/* Escape */
|
||||
{ .keysym = 0xff1b, .scancode = 0x01 },
|
||||
|
||||
/* Home */
|
||||
{ .keysym = 0xff50, .scancode = 0x47,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Left */
|
||||
{ .keysym = 0xff51, .scancode = 0x4B,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Up */
|
||||
{ .keysym = 0xff52, .scancode = 0x48,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Right */
|
||||
{ .keysym = 0xff53, .scancode = 0x4D,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Down */
|
||||
{ .keysym = 0xff54, .scancode = 0x50,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Page_Up */
|
||||
{ .keysym = 0xff55, .scancode = 0x49,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Menu */
|
||||
{ .keysym = 0xff67, .scancode = 0x5D,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Page_Down */
|
||||
{ .keysym = 0xff56, .scancode = 0x51,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* End */
|
||||
{ .keysym = 0xff57, .scancode = 0x4F,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Insert */
|
||||
{ .keysym = 0xff63, .scancode = 0x52,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Num_Lock */
|
||||
{ .keysym = 0xff7f, .scancode = 0x45 },
|
||||
|
||||
/* KP_0 */
|
||||
{ .keysym = 0xffb0, .scancode = 0x52 },
|
||||
|
||||
/* KP_1 */
|
||||
{ .keysym = 0xffb1, .scancode = 0x4F },
|
||||
|
||||
/* KP_2 */
|
||||
{ .keysym = 0xffb2, .scancode = 0x50 },
|
||||
|
||||
/* KP_3 */
|
||||
{ .keysym = 0xffb3, .scancode = 0x51 },
|
||||
|
||||
/* KP_4 */
|
||||
{ .keysym = 0xffb4, .scancode = 0x4B },
|
||||
|
||||
/* KP_5 */
|
||||
{ .keysym = 0xffb5, .scancode = 0x4C },
|
||||
|
||||
/* KP_6 */
|
||||
{ .keysym = 0xffb6, .scancode = 0x4D },
|
||||
|
||||
/* KP_7 */
|
||||
{ .keysym = 0xffb7, .scancode = 0x47 },
|
||||
|
||||
/* KP_8 */
|
||||
{ .keysym = 0xffb8, .scancode = 0x48 },
|
||||
|
||||
/* KP_9 */
|
||||
{ .keysym = 0xffb9, .scancode = 0x49 },
|
||||
|
||||
/* F1 */
|
||||
{ .keysym = 0xffbe, .scancode = 0x3B },
|
||||
|
||||
/* F2 */
|
||||
{ .keysym = 0xffbf, .scancode = 0x3C },
|
||||
|
||||
/* F3 */
|
||||
{ .keysym = 0xffc0, .scancode = 0x3D },
|
||||
|
||||
/* F4 */
|
||||
{ .keysym = 0xffc1, .scancode = 0x3E },
|
||||
|
||||
/* F5 */
|
||||
{ .keysym = 0xffc2, .scancode = 0x3F },
|
||||
|
||||
/* F6 */
|
||||
{ .keysym = 0xffc3, .scancode = 0x40 },
|
||||
|
||||
/* F7 */
|
||||
{ .keysym = 0xffc4, .scancode = 0x41 },
|
||||
|
||||
/* F8 */
|
||||
{ .keysym = 0xffc5, .scancode = 0x42 },
|
||||
|
||||
/* F9 */
|
||||
{ .keysym = 0xffc6, .scancode = 0x43 },
|
||||
|
||||
/* F10 */
|
||||
{ .keysym = 0xffc7, .scancode = 0x44 },
|
||||
|
||||
/* F11 */
|
||||
{ .keysym = 0xffc8, .scancode = 0x57 },
|
||||
|
||||
/* F12 */
|
||||
{ .keysym = 0xffc9, .scancode = 0x58 },
|
||||
|
||||
/* Shift_L */
|
||||
{ .keysym = 0xffe1, .scancode = 0x2A },
|
||||
|
||||
/* Shift_R */
|
||||
{ .keysym = 0xffe2, .scancode = 0x36 },
|
||||
|
||||
/* Control_L */
|
||||
{ .keysym = 0xffe3, .scancode = 0x1D },
|
||||
|
||||
/* Control_R */
|
||||
{ .keysym = 0xffe4, .scancode = 0x9D },
|
||||
|
||||
/* Caps_Lock */
|
||||
{ .keysym = 0xffe5, .scancode = 0x3A,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Alt_L */
|
||||
{ .keysym = 0xffe9, .scancode = 0x38 },
|
||||
|
||||
/* Alt_R */
|
||||
{ .keysym = 0xffea, .scancode = 0x38,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* ISO_Level3_Shift */
|
||||
{ .keysym = 0xfe03, .scancode = 0x38,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Super_L */
|
||||
{ .keysym = 0xffeb, .scancode = 0x5B,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Super_R */
|
||||
{ .keysym = 0xffec, .scancode = 0x5C,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
/* Delete */
|
||||
{ .keysym = 0xffff, .scancode = 0x53,
|
||||
.flags = KBD_FLAGS_EXTENDED },
|
||||
|
||||
{0}
|
||||
|
||||
};
|
||||
|
||||
const guac_rdp_keymap guac_rdp_keymap_base = {
|
||||
|
||||
.name = "base",
|
||||
|
||||
.parent = NULL,
|
||||
.mapping = __guac_rdp_keymap_mapping
|
||||
|
||||
};
|
||||
|
552
protocols/rdp/src/rdp_keymap_de_de.c
Normal file
552
protocols/rdp/src/rdp_keymap_de_de.c
Normal file
@ -0,0 +1,552 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <freerdp/input.h>
|
||||
|
||||
#ifdef HAVE_FREERDP_LOCALE_KEYBOARD_H
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#else
|
||||
#include <freerdp/kbd/layouts.h>
|
||||
#endif
|
||||
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
static guac_rdp_keysym_desc __guac_rdp_keymap_mapping[] = {
|
||||
|
||||
/* space */
|
||||
{ .keysym = 0x0020, .scancode = 0x39 },
|
||||
|
||||
/* exclam */
|
||||
{ .keysym = 0x0021, .scancode = 0x02,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* quotedbl */
|
||||
{ .keysym = 0x0022, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* numbersign */
|
||||
{ .keysym = 0x0023, .scancode = 0x2b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* dollar */
|
||||
{ .keysym = 0x0024, .scancode = 0x05,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* percent */
|
||||
{ .keysym = 0x0025, .scancode = 0x06,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* ampersand */
|
||||
{ .keysym = 0x0026, .scancode = 0x07,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* quoteright */
|
||||
{ .keysym = 0x0027, .scancode = 0x2b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* parenleft */
|
||||
{ .keysym = 0x0028, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* parenright */
|
||||
{ .keysym = 0x0029, .scancode = 0x0A,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* asterisk */
|
||||
{ .keysym = 0x002a, .scancode = 0x1b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* plus */
|
||||
{ .keysym = 0x002b, .scancode = 0x1b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* comma */
|
||||
{ .keysym = 0x002c, .scancode = 0x33,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* minus */
|
||||
{ .keysym = 0x002d, .scancode = 0x35,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* period */
|
||||
{ .keysym = 0x002e, .scancode = 0x34,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* slash */
|
||||
{ .keysym = 0x002f, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 0 */
|
||||
{ .keysym = 0x0030, .scancode = 0x0B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 1 */
|
||||
{ .keysym = 0x0031, .scancode = 0x02,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 2 */
|
||||
{ .keysym = 0x0032, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 3 */
|
||||
{ .keysym = 0x0033, .scancode = 0x04,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 4 */
|
||||
{ .keysym = 0x0034, .scancode = 0x05,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 5 */
|
||||
{ .keysym = 0x0035, .scancode = 0x06,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 6 */
|
||||
{ .keysym = 0x0036, .scancode = 0x07,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 7 */
|
||||
{ .keysym = 0x0037, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 8 */
|
||||
{ .keysym = 0x0038, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* 9 */
|
||||
{ .keysym = 0x0039, .scancode = 0x0A,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* colon */
|
||||
{ .keysym = 0x003a, .scancode = 0x34,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* semicolon */
|
||||
{ .keysym = 0x003b, .scancode = 0x33,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* less */
|
||||
{ .keysym = 0x003c, .scancode = 0x56,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* equal */
|
||||
{ .keysym = 0x003d, .scancode = 0x0B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* greater */
|
||||
{ .keysym = 0x003e, .scancode = 0x56,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* question */
|
||||
{ .keysym = 0x003f, .scancode = 0x0c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* at */
|
||||
{ .keysym = 0x0040, .scancode = 0x10,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* A */
|
||||
{ .keysym = 0x0041, .scancode = 0x1E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* B */
|
||||
{ .keysym = 0x0042, .scancode = 0x30,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* C */
|
||||
{ .keysym = 0x0043, .scancode = 0x2E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* D */
|
||||
{ .keysym = 0x0044, .scancode = 0x20,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* E */
|
||||
{ .keysym = 0x0045, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* F */
|
||||
{ .keysym = 0x0046, .scancode = 0x21,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* G */
|
||||
{ .keysym = 0x0047, .scancode = 0x22,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* H */
|
||||
{ .keysym = 0x0048, .scancode = 0x23,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* I */
|
||||
{ .keysym = 0x0049, .scancode = 0x17,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* J */
|
||||
{ .keysym = 0x004a, .scancode = 0x24,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* K */
|
||||
{ .keysym = 0x004b, .scancode = 0x25,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* L */
|
||||
{ .keysym = 0x004c, .scancode = 0x26,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* M */
|
||||
{ .keysym = 0x004d, .scancode = 0x32,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* N */
|
||||
{ .keysym = 0x004e, .scancode = 0x31,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* O */
|
||||
{ .keysym = 0x004f, .scancode = 0x18,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* P */
|
||||
{ .keysym = 0x0050, .scancode = 0x19,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Q */
|
||||
{ .keysym = 0x0051, .scancode = 0x10,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* R */
|
||||
{ .keysym = 0x0052, .scancode = 0x13,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* S */
|
||||
{ .keysym = 0x0053, .scancode = 0x1F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* T */
|
||||
{ .keysym = 0x0054, .scancode = 0x14,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* U */
|
||||
{ .keysym = 0x0055, .scancode = 0x16,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* V */
|
||||
{ .keysym = 0x0056, .scancode = 0x2F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* W */
|
||||
{ .keysym = 0x0057, .scancode = 0x11,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* X */
|
||||
{ .keysym = 0x0058, .scancode = 0x2D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Y */
|
||||
{ .keysym = 0x0059, .scancode = 0x2c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Z */
|
||||
{ .keysym = 0x005a, .scancode = 0x15,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* bracketleft */
|
||||
{ .keysym = 0x005b, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* backslash */
|
||||
{ .keysym = 0x005c, .scancode = 0x0c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* bracketright */
|
||||
{ .keysym = 0x005d, .scancode = 0x0a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* underscore */
|
||||
{ .keysym = 0x005f, .scancode = 0x35,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* dead grave */
|
||||
{ .keysym = 0xfe50, .scancode = 0x0d,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* dead acute */
|
||||
{ .keysym = 0xfe51, .scancode = 0x0d,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* dead circum */
|
||||
{ .keysym = 0xfe52, .scancode = 0x29,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* degree */
|
||||
{ .keysym = 0x00b0, .scancode = 0x29,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* a */
|
||||
{ .keysym = 0x0061, .scancode = 0x1E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* b */
|
||||
{ .keysym = 0x0062, .scancode = 0x30,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* c */
|
||||
{ .keysym = 0x0063, .scancode = 0x2E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* d */
|
||||
{ .keysym = 0x0064, .scancode = 0x20,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* e */
|
||||
{ .keysym = 0x0065, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* f */
|
||||
{ .keysym = 0x0066, .scancode = 0x21,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* g */
|
||||
{ .keysym = 0x0067, .scancode = 0x22,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* h */
|
||||
{ .keysym = 0x0068, .scancode = 0x23,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* i */
|
||||
{ .keysym = 0x0069, .scancode = 0x17,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* j */
|
||||
{ .keysym = 0x006a, .scancode = 0x24,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* k */
|
||||
{ .keysym = 0x006b, .scancode = 0x25,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* l */
|
||||
{ .keysym = 0x006c, .scancode = 0x26,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* m */
|
||||
{ .keysym = 0x006d, .scancode = 0x32,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* n */
|
||||
{ .keysym = 0x006e, .scancode = 0x31,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* o */
|
||||
{ .keysym = 0x006f, .scancode = 0x18,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* p */
|
||||
{ .keysym = 0x0070, .scancode = 0x19,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* q */
|
||||
{ .keysym = 0x0071, .scancode = 0x10,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* r */
|
||||
{ .keysym = 0x0072, .scancode = 0x13,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* s */
|
||||
{ .keysym = 0x0073, .scancode = 0x1F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* t */
|
||||
{ .keysym = 0x0074, .scancode = 0x14,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* u */
|
||||
{ .keysym = 0x0075, .scancode = 0x16,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* v */
|
||||
{ .keysym = 0x0076, .scancode = 0x2F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* w */
|
||||
{ .keysym = 0x0077, .scancode = 0x11,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* x */
|
||||
{ .keysym = 0x0078, .scancode = 0x2D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* y */
|
||||
{ .keysym = 0x0079, .scancode = 0x2c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* z */
|
||||
{ .keysym = 0x007a, .scancode = 0x15,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* ä */
|
||||
{ .keysym = 0x00e4, .scancode = 0x28,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* Ä */
|
||||
{ .keysym = 0x00c4, .scancode = 0x28,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* ö */
|
||||
{ .keysym = 0x00f6, .scancode = 0x27,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* Ö */
|
||||
{ .keysym = 0x00d6, .scancode = 0x27,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* ü */
|
||||
{ .keysym = 0x00fc, .scancode = 0x1a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* Ü */
|
||||
{ .keysym = 0x00dc, .scancode = 0x1a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* ß */
|
||||
{ .keysym = 0x00df, .scancode = 0x0c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* braceleft */
|
||||
{ .keysym = 0x007b, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* bar */
|
||||
{ .keysym = 0x007c, .scancode = 0x56,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* braceright */
|
||||
{ .keysym = 0x007d, .scancode = 0x0b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* dead tilde */
|
||||
{ .keysym = 0xfe53, .scancode = 0x1b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* euro */
|
||||
{ .keysym = 0x10020ac, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* mu */
|
||||
{ .keysym = 0x00b5, .scancode = 0x32,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* two superior */
|
||||
{ .keysym = 0x00b2, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* three superior */
|
||||
{ .keysym = 0x00b3, .scancode = 0x04,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
{0}
|
||||
|
||||
};
|
||||
|
||||
const guac_rdp_keymap guac_rdp_keymap_de_de = {
|
||||
|
||||
.name = "de-de-qwertz",
|
||||
|
||||
.parent = &guac_rdp_keymap_base,
|
||||
.mapping = __guac_rdp_keymap_mapping,
|
||||
.freerdp_keyboard_layout = KBD_GERMAN
|
||||
|
||||
};
|
||||
|
442
protocols/rdp/src/rdp_keymap_en_us.c
Normal file
442
protocols/rdp/src/rdp_keymap_en_us.c
Normal file
@ -0,0 +1,442 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Hortman
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <freerdp/input.h>
|
||||
|
||||
#ifdef HAVE_FREERDP_LOCALE_KEYBOARD_H
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#else
|
||||
#include <freerdp/kbd/layouts.h>
|
||||
#endif
|
||||
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
static guac_rdp_keysym_desc __guac_rdp_keymap_mapping[] = {
|
||||
|
||||
/* space */
|
||||
{ .keysym = 0x0020, .scancode = 0x39 },
|
||||
|
||||
/* exclam */
|
||||
{ .keysym = 0x0021, .scancode = 0x02,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* quotedbl */
|
||||
{ .keysym = 0x0022, .scancode = 0x28,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* numbersign */
|
||||
{ .keysym = 0x0023, .scancode = 0x04,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* dollar */
|
||||
{ .keysym = 0x0024, .scancode = 0x05,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* percent */
|
||||
{ .keysym = 0x0025, .scancode = 0x06,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* ampersand */
|
||||
{ .keysym = 0x0026, .scancode = 0x08,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* quoteright */
|
||||
{ .keysym = 0x0027, .scancode = 0x28 },
|
||||
|
||||
/* parenleft */
|
||||
{ .keysym = 0x0028, .scancode = 0x0A,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* parenright */
|
||||
{ .keysym = 0x0029, .scancode = 0x0B,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* asterisk */
|
||||
{ .keysym = 0x002a, .scancode = 0x09,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* plus */
|
||||
{ .keysym = 0x002b, .scancode = 0x0D,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* comma */
|
||||
{ .keysym = 0x002c, .scancode = 0x33,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* minus */
|
||||
{ .keysym = 0x002d, .scancode = 0x0C,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* period */
|
||||
{ .keysym = 0x002e, .scancode = 0x34,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* slash */
|
||||
{ .keysym = 0x002f, .scancode = 0x35,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 0 */
|
||||
{ .keysym = 0x0030, .scancode = 0x0B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 1 */
|
||||
{ .keysym = 0x0031, .scancode = 0x02,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 2 */
|
||||
{ .keysym = 0x0032, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 3 */
|
||||
{ .keysym = 0x0033, .scancode = 0x04,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 4 */
|
||||
{ .keysym = 0x0034, .scancode = 0x05,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 5 */
|
||||
{ .keysym = 0x0035, .scancode = 0x06,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 6 */
|
||||
{ .keysym = 0x0036, .scancode = 0x07,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 7 */
|
||||
{ .keysym = 0x0037, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 8 */
|
||||
{ .keysym = 0x0038, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* 9 */
|
||||
{ .keysym = 0x0039, .scancode = 0x0A,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* colon */
|
||||
{ .keysym = 0x003a, .scancode = 0x27,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* semicolon */
|
||||
{ .keysym = 0x003b, .scancode = 0x27,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* less */
|
||||
{ .keysym = 0x003c, .scancode = 0x33,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* equal */
|
||||
{ .keysym = 0x003d, .scancode = 0x0D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* greater */
|
||||
{ .keysym = 0x003e, .scancode = 0x34,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* question */
|
||||
{ .keysym = 0x003f, .scancode = 0x35,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* at */
|
||||
{ .keysym = 0x0040, .scancode = 0x03,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* A */
|
||||
{ .keysym = 0x0041, .scancode = 0x1E,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* B */
|
||||
{ .keysym = 0x0042, .scancode = 0x30,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* C */
|
||||
{ .keysym = 0x0043, .scancode = 0x2E,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* D */
|
||||
{ .keysym = 0x0044, .scancode = 0x20,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* E */
|
||||
{ .keysym = 0x0045, .scancode = 0x12,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* F */
|
||||
{ .keysym = 0x0046, .scancode = 0x21,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* G */
|
||||
{ .keysym = 0x0047, .scancode = 0x22,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* H */
|
||||
{ .keysym = 0x0048, .scancode = 0x23,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* I */
|
||||
{ .keysym = 0x0049, .scancode = 0x17,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* J */
|
||||
{ .keysym = 0x004a, .scancode = 0x24,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* K */
|
||||
{ .keysym = 0x004b, .scancode = 0x25,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* L */
|
||||
{ .keysym = 0x004c, .scancode = 0x26,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* M */
|
||||
{ .keysym = 0x004d, .scancode = 0x32,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* N */
|
||||
{ .keysym = 0x004e, .scancode = 0x31,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* O */
|
||||
{ .keysym = 0x004f, .scancode = 0x18,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* P */
|
||||
{ .keysym = 0x0050, .scancode = 0x19,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Q */
|
||||
{ .keysym = 0x0051, .scancode = 0x10,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* R */
|
||||
{ .keysym = 0x0052, .scancode = 0x13,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* S */
|
||||
{ .keysym = 0x0053, .scancode = 0x1F,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* T */
|
||||
{ .keysym = 0x0054, .scancode = 0x14,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* U */
|
||||
{ .keysym = 0x0055, .scancode = 0x16,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* V */
|
||||
{ .keysym = 0x0056, .scancode = 0x2F,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* W */
|
||||
{ .keysym = 0x0057, .scancode = 0x11,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* X */
|
||||
{ .keysym = 0x0058, .scancode = 0x2D,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Y */
|
||||
{ .keysym = 0x0059, .scancode = 0x15,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Z */
|
||||
{ .keysym = 0x005a, .scancode = 0x2C,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* bracketleft */
|
||||
{ .keysym = 0x005b, .scancode = 0x1A,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* backslash */
|
||||
{ .keysym = 0x005c, .scancode = 0x2B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* bracketright */
|
||||
{ .keysym = 0x005d, .scancode = 0x1B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* asciicircum */
|
||||
{ .keysym = 0x005e, .scancode = 0x07,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* underscore */
|
||||
{ .keysym = 0x005f, .scancode = 0x0C,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* quoteleft */
|
||||
{ .keysym = 0x0060, .scancode = 0x29,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* a */
|
||||
{ .keysym = 0x0061, .scancode = 0x1E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* b */
|
||||
{ .keysym = 0x0062, .scancode = 0x30,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* c */
|
||||
{ .keysym = 0x0063, .scancode = 0x2E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* d */
|
||||
{ .keysym = 0x0064, .scancode = 0x20,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* e */
|
||||
{ .keysym = 0x0065, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* f */
|
||||
{ .keysym = 0x0066, .scancode = 0x21,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* g */
|
||||
{ .keysym = 0x0067, .scancode = 0x22,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* h */
|
||||
{ .keysym = 0x0068, .scancode = 0x23,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* i */
|
||||
{ .keysym = 0x0069, .scancode = 0x17,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* j */
|
||||
{ .keysym = 0x006a, .scancode = 0x24,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* k */
|
||||
{ .keysym = 0x006b, .scancode = 0x25,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* l */
|
||||
{ .keysym = 0x006c, .scancode = 0x26,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* m */
|
||||
{ .keysym = 0x006d, .scancode = 0x32,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* n */
|
||||
{ .keysym = 0x006e, .scancode = 0x31,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* o */
|
||||
{ .keysym = 0x006f, .scancode = 0x18,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* p */
|
||||
{ .keysym = 0x0070, .scancode = 0x19,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* q */
|
||||
{ .keysym = 0x0071, .scancode = 0x10,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* r */
|
||||
{ .keysym = 0x0072, .scancode = 0x13,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* s */
|
||||
{ .keysym = 0x0073, .scancode = 0x1F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* t */
|
||||
{ .keysym = 0x0074, .scancode = 0x14,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* u */
|
||||
{ .keysym = 0x0075, .scancode = 0x16,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* v */
|
||||
{ .keysym = 0x0076, .scancode = 0x2F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* w */
|
||||
{ .keysym = 0x0077, .scancode = 0x11,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* x */
|
||||
{ .keysym = 0x0078, .scancode = 0x2D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* y */
|
||||
{ .keysym = 0x0079, .scancode = 0x15,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* z */
|
||||
{ .keysym = 0x007a, .scancode = 0x2C,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT },
|
||||
|
||||
/* braceleft */
|
||||
{ .keysym = 0x007b, .scancode = 0x1A,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* bar */
|
||||
{ .keysym = 0x007c, .scancode = 0x2B,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* braceright */
|
||||
{ .keysym = 0x007d, .scancode = 0x1B,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* asciitilde */
|
||||
{ .keysym = 0x007e, .scancode = 0x29,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
{0}
|
||||
|
||||
};
|
||||
|
||||
const guac_rdp_keymap guac_rdp_keymap_en_us = {
|
||||
|
||||
.name = "en-us-qwerty",
|
||||
|
||||
.parent = &guac_rdp_keymap_base,
|
||||
.mapping = __guac_rdp_keymap_mapping,
|
||||
.freerdp_keyboard_layout = KBD_US
|
||||
|
||||
};
|
||||
|
63
protocols/rdp/src/rdp_keymap_failsafe.c
Normal file
63
protocols/rdp/src/rdp_keymap_failsafe.c
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <freerdp/input.h>
|
||||
|
||||
#ifdef HAVE_FREERDP_LOCALE_KEYBOARD_H
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#else
|
||||
#include <freerdp/kbd/layouts.h>
|
||||
#endif
|
||||
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
static guac_rdp_keysym_desc __guac_rdp_keymap_mapping[] = {
|
||||
|
||||
{0}
|
||||
|
||||
};
|
||||
|
||||
const guac_rdp_keymap guac_rdp_keymap_failsafe = {
|
||||
|
||||
.name = "failsafe",
|
||||
|
||||
.parent = &guac_rdp_keymap_base,
|
||||
.mapping = __guac_rdp_keymap_mapping,
|
||||
.freerdp_keyboard_layout = KBD_US
|
||||
|
||||
};
|
||||
|
560
protocols/rdp/src/rdp_keymap_fr_fr.c
Normal file
560
protocols/rdp/src/rdp_keymap_fr_fr.c
Normal file
@ -0,0 +1,560 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alexandre Devely
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <freerdp/input.h>
|
||||
|
||||
#ifdef HAVE_FREERDP_LOCALE_KEYBOARD_H
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#else
|
||||
#include <freerdp/kbd/layouts.h>
|
||||
#endif
|
||||
|
||||
#include "rdp_keymap.h"
|
||||
|
||||
|
||||
static guac_rdp_keysym_desc __guac_rdp_keymap_mapping[] = {
|
||||
|
||||
/* space */
|
||||
{ .keysym = 0x0020, .scancode = 0x39 },
|
||||
|
||||
/* exclam */
|
||||
{ .keysym = 0x0021, .scancode = 0x35,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* quotedbl */
|
||||
{ .keysym = 0x0022, .scancode = 0x04,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* numbersign */
|
||||
{ .keysym = 0x0023, .scancode = 0x04,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* dollar */
|
||||
{ .keysym = 0x0024, .scancode = 0x1b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* percent */
|
||||
{ .keysym = 0x0025, .scancode = 0x28,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* ampersand */
|
||||
{ .keysym = 0x0026, .scancode = 0x02,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* quoteright */
|
||||
{ .keysym = 0x0027, .scancode = 0x05,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* parenleft */
|
||||
{ .keysym = 0x0028, .scancode = 0x06,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* parenright */
|
||||
{ .keysym = 0x0029, .scancode = 0x0c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* asterisk */
|
||||
{ .keysym = 0x002a, .scancode = 0x2b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* plus */
|
||||
{ .keysym = 0x002b, .scancode = 0x0D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* comma */
|
||||
{ .keysym = 0x002c, .scancode = 0x32,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* minus */
|
||||
{ .keysym = 0x002d, .scancode = 0x07,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* period */
|
||||
{ .keysym = 0x002e, .scancode = 0x33,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* slash */
|
||||
{ .keysym = 0x002f, .scancode = 0x34,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 0 */
|
||||
{ .keysym = 0x0030, .scancode = 0x0B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 1 */
|
||||
{ .keysym = 0x0031, .scancode = 0x02,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 2 */
|
||||
{ .keysym = 0x0032, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 3 */
|
||||
{ .keysym = 0x0033, .scancode = 0x04,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 4 */
|
||||
{ .keysym = 0x0034, .scancode = 0x05,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 5 */
|
||||
{ .keysym = 0x0035, .scancode = 0x06,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 6 */
|
||||
{ .keysym = 0x0036, .scancode = 0x07,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 7 */
|
||||
{ .keysym = 0x0037, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 8 */
|
||||
{ .keysym = 0x0038, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* 9 */
|
||||
{ .keysym = 0x0039, .scancode = 0x0A,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* colon */
|
||||
{ .keysym = 0x003a, .scancode = 0x34,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* semicolon */
|
||||
{ .keysym = 0x003b, .scancode = 0x33,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* less */
|
||||
{ .keysym = 0x003c, .scancode = 0x56,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* equal */
|
||||
{ .keysym = 0x003d, .scancode = 0x0D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* greater */
|
||||
{ .keysym = 0x003e, .scancode = 0x56,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* question */
|
||||
{ .keysym = 0x003f, .scancode = 0x32,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* at */
|
||||
{ .keysym = 0x0040, .scancode = 0x0B,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* A */
|
||||
{ .keysym = 0x0041, .scancode = 0x10,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* B */
|
||||
{ .keysym = 0x0042, .scancode = 0x30,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* C */
|
||||
{ .keysym = 0x0043, .scancode = 0x2E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* D */
|
||||
{ .keysym = 0x0044, .scancode = 0x20,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* E */
|
||||
{ .keysym = 0x0045, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* F */
|
||||
{ .keysym = 0x0046, .scancode = 0x21,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* G */
|
||||
{ .keysym = 0x0047, .scancode = 0x22,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* H */
|
||||
{ .keysym = 0x0048, .scancode = 0x23,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* I */
|
||||
{ .keysym = 0x0049, .scancode = 0x17,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* J */
|
||||
{ .keysym = 0x004a, .scancode = 0x24,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* K */
|
||||
{ .keysym = 0x004b, .scancode = 0x25,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* L */
|
||||
{ .keysym = 0x004c, .scancode = 0x26,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* M */
|
||||
{ .keysym = 0x004d, .scancode = 0x27,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* N */
|
||||
{ .keysym = 0x004e, .scancode = 0x31,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* O */
|
||||
{ .keysym = 0x004f, .scancode = 0x18,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* P */
|
||||
{ .keysym = 0x0050, .scancode = 0x19,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Q */
|
||||
{ .keysym = 0x0051, .scancode = 0x1E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* R */
|
||||
{ .keysym = 0x0052, .scancode = 0x13,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* S */
|
||||
{ .keysym = 0x0053, .scancode = 0x1F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* T */
|
||||
{ .keysym = 0x0054, .scancode = 0x14,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* U */
|
||||
{ .keysym = 0x0055, .scancode = 0x16,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* V */
|
||||
{ .keysym = 0x0056, .scancode = 0x2F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* W */
|
||||
{ .keysym = 0x0057, .scancode = 0x2C,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* X */
|
||||
{ .keysym = 0x0058, .scancode = 0x2D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Y */
|
||||
{ .keysym = 0x0059, .scancode = 0x15,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* Z */
|
||||
{ .keysym = 0x005a, .scancode = 0x11,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* bracketleft */
|
||||
{ .keysym = 0x005b, .scancode = 0x06,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* backslash */
|
||||
{ .keysym = 0x005c, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* bracketright */
|
||||
{ .keysym = 0x005d, .scancode = 0x0c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* asciicircum */
|
||||
{ .keysym = 0x005e, .scancode = 0x0a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* underscore */
|
||||
{ .keysym = 0x005f, .scancode = 0x09,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* quoteleft */
|
||||
{ .keysym = 0x0060, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* a */
|
||||
{ .keysym = 0x0061, .scancode = 0x10,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* b */
|
||||
{ .keysym = 0x0062, .scancode = 0x30,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* c */
|
||||
{ .keysym = 0x0063, .scancode = 0x2E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* d */
|
||||
{ .keysym = 0x0064, .scancode = 0x20,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* e */
|
||||
{ .keysym = 0x0065, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* f */
|
||||
{ .keysym = 0x0066, .scancode = 0x21,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* g */
|
||||
{ .keysym = 0x0067, .scancode = 0x22,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* h */
|
||||
{ .keysym = 0x0068, .scancode = 0x23,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* i */
|
||||
{ .keysym = 0x0069, .scancode = 0x17,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* j */
|
||||
{ .keysym = 0x006a, .scancode = 0x24,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* k */
|
||||
{ .keysym = 0x006b, .scancode = 0x25,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* l */
|
||||
{ .keysym = 0x006c, .scancode = 0x26,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* m */
|
||||
{ .keysym = 0x006d, .scancode = 0x27,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* n */
|
||||
{ .keysym = 0x006e, .scancode = 0x31,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* o */
|
||||
{ .keysym = 0x006f, .scancode = 0x18,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* p */
|
||||
{ .keysym = 0x0070, .scancode = 0x19,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* q */
|
||||
{ .keysym = 0x0071, .scancode = 0x1E,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* r */
|
||||
{ .keysym = 0x0072, .scancode = 0x13,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* s */
|
||||
{ .keysym = 0x0073, .scancode = 0x1F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* t */
|
||||
{ .keysym = 0x0074, .scancode = 0x14,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* u */
|
||||
{ .keysym = 0x0075, .scancode = 0x16,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* v */
|
||||
{ .keysym = 0x0076, .scancode = 0x2F,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* w */
|
||||
{ .keysym = 0x0077, .scancode = 0x2C,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* x */
|
||||
{ .keysym = 0x0078, .scancode = 0x2D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* y */
|
||||
{ .keysym = 0x0079, .scancode = 0x15,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* z */
|
||||
{ .keysym = 0x007a, .scancode = 0x11,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* braceleft */
|
||||
{ .keysym = 0x007b, .scancode = 0x05,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* bar */
|
||||
{ .keysym = 0x007c, .scancode = 0x07,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* braceright */
|
||||
{ .keysym = 0x007d, .scancode = 0x0D,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* asciitilde */
|
||||
{ .keysym = 0x007e, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* pound */
|
||||
{ .keysym = 0x00a3, .scancode = 0x1b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* currency */
|
||||
{ .keysym = 0x00a4, .scancode = 0x1b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* section */
|
||||
{ .keysym = 0x00a7, .scancode = 0x35,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* degree */
|
||||
{ .keysym = 0x00b0, .scancode = 0x0c,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* micro */
|
||||
{ .keysym = 0x00b5, .scancode = 0x2b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* dead umlaut */
|
||||
{ .keysym = 0xfe57, .scancode = 0x1a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALTGR,
|
||||
.set_keysyms = GUAC_KEYSYMS_SHIFT },
|
||||
|
||||
/* dead circum */
|
||||
{ .keysym = 0xfe52, .scancode = 0x1a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* à */
|
||||
{ .keysym = 0x00e0, .scancode = 0x0b,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* ç */
|
||||
{ .keysym = 0x00e7, .scancode = 0x0a,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* è */
|
||||
{ .keysym = 0x00e8, .scancode = 0x08,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* é */
|
||||
{ .keysym = 0x00e9, .scancode = 0x03,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* ù */
|
||||
{ .keysym = 0x00f9, .scancode = 0x28,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
/* euro */
|
||||
{ .keysym = 0x10020ac, .scancode = 0x12,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT,
|
||||
.set_keysyms = GUAC_KEYSYMS_ALTGR },
|
||||
|
||||
/* two superior */
|
||||
{ .keysym = 0x00b2, .scancode = 0x29,
|
||||
.clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR },
|
||||
|
||||
{0}
|
||||
|
||||
};
|
||||
|
||||
const guac_rdp_keymap guac_rdp_keymap_fr_fr = {
|
||||
|
||||
.name = "fr-fr-azerty",
|
||||
|
||||
.parent = &guac_rdp_keymap_base,
|
||||
.mapping = __guac_rdp_keymap_mapping,
|
||||
.freerdp_keyboard_layout = KBD_FRENCH
|
||||
|
||||
};
|
||||
|
120
protocols/rdp/src/rdp_pointer.c
Normal file
120
protocols/rdp/src/rdp_pointer.c
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David PHAM-VAN <d.pham-van@ulteo.com> Ulteo SAS - http://www.ulteo.com
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_pointer.h"
|
||||
#include "default_pointer.h"
|
||||
|
||||
void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
/* Allocate data for image */
|
||||
unsigned char* data =
|
||||
(unsigned char*) malloc(pointer->width * pointer->height * 4);
|
||||
|
||||
/* Allocate layer */
|
||||
guac_layer* buffer = guac_client_alloc_buffer(client);
|
||||
|
||||
cairo_surface_t* surface;
|
||||
|
||||
rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(client_data->update_lock));
|
||||
|
||||
/* Convert to alpha cursor if mask data present */
|
||||
if (pointer->andMaskData && pointer->xorMaskData)
|
||||
freerdp_alpha_cursor_convert(data,
|
||||
pointer->xorMaskData, pointer->andMaskData,
|
||||
pointer->width, pointer->height, pointer->xorBpp,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
/* Create surface from image data */
|
||||
surface = cairo_image_surface_create_for_data(
|
||||
data, CAIRO_FORMAT_ARGB32,
|
||||
pointer->width, pointer->height, 4*pointer->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket, GUAC_COMP_SRC, buffer, 0, 0, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
free(data);
|
||||
|
||||
/* Remember buffer */
|
||||
((guac_rdp_pointer*) pointer)->layer = buffer;
|
||||
|
||||
pthread_mutex_unlock(&(client_data->update_lock));
|
||||
}
|
||||
|
||||
void guac_rdp_pointer_set(rdpContext* context, rdpPointer* pointer) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket* socket = client->socket;
|
||||
|
||||
rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;
|
||||
pthread_mutex_lock(&(data->update_lock));
|
||||
|
||||
/* Set cursor */
|
||||
guac_protocol_send_cursor(socket, pointer->xPos, pointer->yPos,
|
||||
((guac_rdp_pointer*) pointer)->layer,
|
||||
0, 0, pointer->width, pointer->height);
|
||||
|
||||
pthread_mutex_unlock(&(data->update_lock));
|
||||
}
|
||||
|
||||
void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_client_free_buffer(client, ((guac_rdp_pointer*) pointer)->layer);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_pointer_set_null(rdpContext* context) {
|
||||
/* STUB */
|
||||
}
|
||||
|
||||
void guac_rdp_pointer_set_default(rdpContext* context) {
|
||||
/* STUB */
|
||||
}
|
||||
|
201
protocols/rdp/src/wav_encoder.c
Normal file
201
protocols/rdp/src/wav_encoder.c
Normal file
@ -0,0 +1,201 @@
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libguac-client-rdp.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Jumper.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define WAV_BUFFER_SIZE 0x4000
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "wav_encoder.h"
|
||||
|
||||
void wav_encoder_begin_handler(audio_stream* audio) {
|
||||
|
||||
/* Allocate stream state */
|
||||
wav_encoder_state* state = (wav_encoder_state*)
|
||||
malloc(sizeof(wav_encoder_state));
|
||||
|
||||
/* Initialize buffer */
|
||||
state->length = WAV_BUFFER_SIZE;
|
||||
state->used = 0;
|
||||
state->data_buffer = (unsigned char*) malloc(state->length);
|
||||
|
||||
audio->data = state;
|
||||
|
||||
}
|
||||
|
||||
void _wav_encoder_write_le(unsigned char* buffer, int value, int length) {
|
||||
|
||||
int offset;
|
||||
|
||||
/* Write all bytes in the given value in little-endian byte order */
|
||||
for (offset=0; offset<length; offset++) {
|
||||
|
||||
/* Store byte */
|
||||
*buffer = value & 0xFF;
|
||||
|
||||
/* Move to next byte */
|
||||
value >>= 8;
|
||||
buffer++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void wav_encoder_end_handler(audio_stream* audio) {
|
||||
|
||||
/*
|
||||
* Static header init
|
||||
*/
|
||||
|
||||
wav_encoder_riff_header riff_header = {
|
||||
.chunk_id = "RIFF",
|
||||
.chunk_format = "WAVE"
|
||||
};
|
||||
|
||||
wav_encoder_fmt_header fmt_header = {
|
||||
.subchunk_id = "fmt ",
|
||||
.subchunk_size = {0x10, 0x00, 0x00, 0x00}, /* 16 */
|
||||
.subchunk_format = {0x01, 0x00} /* 1 = PCM */
|
||||
};
|
||||
|
||||
wav_encoder_data_header data_header = {
|
||||
.subchunk_id = "data"
|
||||
};
|
||||
|
||||
/* Get state */
|
||||
wav_encoder_state* state = (wav_encoder_state*) audio->data;
|
||||
|
||||
/*
|
||||
* RIFF HEADER
|
||||
*/
|
||||
|
||||
/* Chunk size */
|
||||
_wav_encoder_write_le(riff_header.chunk_size,
|
||||
4 + sizeof(fmt_header) + sizeof(data_header) + state->used,
|
||||
sizeof(riff_header.chunk_size));
|
||||
|
||||
audio_stream_write_encoded(audio,
|
||||
(unsigned char*) &riff_header,
|
||||
sizeof(riff_header));
|
||||
|
||||
/*
|
||||
* FMT HEADER
|
||||
*/
|
||||
|
||||
/* Channels */
|
||||
_wav_encoder_write_le(fmt_header.subchunk_channels,
|
||||
audio->channels, sizeof(fmt_header.subchunk_channels));
|
||||
|
||||
/* Sample rate */
|
||||
_wav_encoder_write_le(fmt_header.subchunk_sample_rate,
|
||||
audio->rate, sizeof(fmt_header.subchunk_sample_rate));
|
||||
|
||||
/* Byte rate */
|
||||
_wav_encoder_write_le(fmt_header.subchunk_byte_rate,
|
||||
audio->rate * audio->channels * audio->bps / 8,
|
||||
sizeof(fmt_header.subchunk_byte_rate));
|
||||
|
||||
/* Block align */
|
||||
_wav_encoder_write_le(fmt_header.subchunk_block_align,
|
||||
audio->channels * audio->bps / 8,
|
||||
sizeof(fmt_header.subchunk_block_align));
|
||||
|
||||
/* Bits per second */
|
||||
_wav_encoder_write_le(fmt_header.subchunk_bps,
|
||||
audio->bps, sizeof(fmt_header.subchunk_bps));
|
||||
|
||||
audio_stream_write_encoded(audio,
|
||||
(unsigned char*) &fmt_header,
|
||||
sizeof(fmt_header));
|
||||
|
||||
/*
|
||||
* DATA HEADER
|
||||
*/
|
||||
|
||||
/* PCM data size */
|
||||
_wav_encoder_write_le(data_header.subchunk_size,
|
||||
state->used, sizeof(data_header.subchunk_size));
|
||||
|
||||
audio_stream_write_encoded(audio,
|
||||
(unsigned char*) &data_header,
|
||||
sizeof(data_header));
|
||||
|
||||
/* Write .wav data */
|
||||
audio_stream_write_encoded(audio, state->data_buffer, state->used);
|
||||
|
||||
/* Free stream state */
|
||||
free(state);
|
||||
|
||||
}
|
||||
|
||||
void wav_encoder_write_handler(audio_stream* audio,
|
||||
unsigned char* pcm_data, int length) {
|
||||
|
||||
/* Get state */
|
||||
wav_encoder_state* state = (wav_encoder_state*) audio->data;
|
||||
|
||||
/* Increase size of buffer if necessary */
|
||||
if (state->used + length > state->length) {
|
||||
|
||||
/* Increase to double concatenated size to accomodate */
|
||||
state->length = (state->length + length)*2;
|
||||
state->data_buffer = realloc(state->data_buffer,
|
||||
state->length);
|
||||
|
||||
}
|
||||
|
||||
/* Append to buffer */
|
||||
memcpy(&(state->data_buffer[state->used]), pcm_data, length);
|
||||
state->used += length;
|
||||
|
||||
}
|
||||
|
||||
/* Encoder handlers */
|
||||
audio_encoder _wav_encoder = {
|
||||
.mimetype = "audio/wav",
|
||||
.begin_handler = wav_encoder_begin_handler,
|
||||
.write_handler = wav_encoder_write_handler,
|
||||
.end_handler = wav_encoder_end_handler
|
||||
};
|
||||
|
||||
/* Actual encoder */
|
||||
audio_encoder* wav_encoder = &_wav_encoder;
|
||||
|
Loading…
Reference in New Issue
Block a user