You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by mj...@apache.org on 2020/01/26 22:06:37 UTC

[guacamole-website] branch asf-site updated: Deploy documentation and draft release notes for 1.1.0-RC1.

This is an automated email from the ASF dual-hosted git repository.

mjumper pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/guacamole-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 443b7cc  Deploy documentation and draft release notes for 1.1.0-RC1.
443b7cc is described below

commit 443b7cc276df1fe75e159ded10be840117fa8512
Author: Michael Jumper <mj...@apache.org>
AuthorDate: Sun Jan 26 14:06:20 2020 -0800

    Deploy documentation and draft release notes for 1.1.0-RC1.
---
 .../guacamole-common-js/ArrayBufferReader.js.html  |  136 +
 .../guacamole-common-js/ArrayBufferWriter.js.html  |  184 +
 .../AudioContextFactory.js.html                    |  140 +
 .../1.1.0/guacamole-common-js/AudioPlayer.js.html  |  566 ++
 .../guacamole-common-js/AudioRecorder.js.html      |  632 ++
 .../1.1.0/guacamole-common-js/BlobReader.js.html   |  188 +
 .../1.1.0/guacamole-common-js/BlobWriter.js.html   |  306 +
 .../doc/1.1.0/guacamole-common-js/Client.js.html   | 1751 ++++
 .../guacamole-common-js/DataURIReader.js.html      |  144 +
 .../doc/1.1.0/guacamole-common-js/Display.js.html  | 1543 ++++
 .../Guacamole.ArrayBufferReader.html               |  456 +
 .../Guacamole.ArrayBufferWriter.html               |  758 ++
 .../Guacamole.AudioContextFactory.html             |  341 +
 .../guacamole-common-js/Guacamole.AudioPlayer.html |  734 ++
 .../Guacamole.AudioRecorder.html                   |  828 ++
 .../guacamole-common-js/Guacamole.BlobReader.html  |  700 ++
 .../guacamole-common-js/Guacamole.BlobWriter.html  | 1073 +++
 .../Guacamole.ChainedTunnel.html                   | 1527 ++++
 .../guacamole-common-js/Guacamole.Client.html      | 5195 +++++++++++
 .../Guacamole.DataURIReader.html                   |  435 +
 .../Guacamole.Display.VisibleLayer.html            | 6600 ++++++++++++++
 .../guacamole-common-js/Guacamole.Display.html     | 9066 ++++++++++++++++++++
 .../guacamole-common-js/Guacamole.HTTPTunnel.html  | 1609 ++++
 .../guacamole-common-js/Guacamole.InputSink.html   |  380 +
 .../guacamole-common-js/Guacamole.InputStream.html |  716 ++
 .../guacamole-common-js/Guacamole.IntegerPool.html |  504 ++
 .../guacamole-common-js/Guacamole.JSONReader.html  |  678 ++
 .../Guacamole.Keyboard.ModifierState.html          |  705 ++
 .../guacamole-common-js/Guacamole.Keyboard.html    | 1666 ++++
 .../guacamole-common-js/Guacamole.Layer.Pixel.html |  554 ++
 .../1.1.0/guacamole-common-js/Guacamole.Layer.html | 5716 ++++++++++++
 .../guacamole-common-js/Guacamole.Mouse.State.html | 1069 +++
 .../Guacamole.Mouse.Touchpad.html                  |  914 ++
 .../Guacamole.Mouse.Touchscreen.html               |  980 +++
 .../1.1.0/guacamole-common-js/Guacamole.Mouse.html | 1286 +++
 .../guacamole-common-js/Guacamole.Object.html      | 1120 +++
 .../Guacamole.OnScreenKeyboard.Key.html            |  656 ++
 .../Guacamole.OnScreenKeyboard.Layout.html         |  687 ++
 .../Guacamole.OnScreenKeyboard.html                |  986 +++
 .../Guacamole.OutputStream.html                    |  692 ++
 .../guacamole-common-js/Guacamole.Parser.html      |  484 ++
 .../Guacamole.RawAudioFormat.html                  |  621 ++
 .../Guacamole.RawAudioPlayer.html                  |  638 ++
 .../Guacamole.RawAudioRecorder.html                |  814 ++
 .../Guacamole.SessionRecording.html                | 1715 ++++
 .../Guacamole.StaticHTTPTunnel.html                | 1611 ++++
 .../guacamole-common-js/Guacamole.Status.html      |  606 ++
 .../Guacamole.StringReader.html                    |  456 +
 .../Guacamole.StringWriter.html                    |  595 ++
 .../guacamole-common-js/Guacamole.Tunnel.html      | 1545 ++++
 .../guacamole-common-js/Guacamole.VideoPlayer.html |  756 ++
 .../Guacamole.WebSocketTunnel.html                 | 1511 ++++
 .../doc/1.1.0/guacamole-common-js/Guacamole.html   |  332 +
 .../1.1.0/guacamole-common-js/InputSink.js.html    |  189 +
 .../1.1.0/guacamole-common-js/InputStream.js.html  |  131 +
 .../1.1.0/guacamole-common-js/IntegerPool.js.html  |  137 +
 .../1.1.0/guacamole-common-js/JSONReader.js.html   |  175 +
 .../doc/1.1.0/guacamole-common-js/Keyboard.js.html | 1574 ++++
 .../doc/1.1.0/guacamole-common-js/Layer.js.html    | 1039 +++
 .../doc/1.1.0/guacamole-common-js/Mouse.js.html    | 1148 +++
 .../1.1.0/guacamole-common-js/Namespace.js.html    |   87 +
 .../doc/1.1.0/guacamole-common-js/Object.js.html   |  271 +
 .../guacamole-common-js/OnScreenKeyboard.js.html   | 1004 +++
 .../1.1.0/guacamole-common-js/OutputStream.js.html |  129 +
 .../doc/1.1.0/guacamole-common-js/Parser.js.html   |  217 +
 .../guacamole-common-js/RawAudioFormat.js.html     |  207 +
 .../guacamole-common-js/SessionRecording.js.html   |  880 ++
 .../doc/1.1.0/guacamole-common-js/Status.js.html   |  379 +
 .../1.1.0/guacamole-common-js/StringReader.js.html |  227 +
 .../1.1.0/guacamole-common-js/StringWriter.js.html |  252 +
 .../doc/1.1.0/guacamole-common-js/Tunnel.js.html   | 1445 ++++
 .../doc/1.1.0/guacamole-common-js/Version.js.html  |   91 +
 .../1.1.0/guacamole-common-js/VideoPlayer.js.html  |  169 +
 .../fonts/OpenSans-Bold-webfont.eot                |  Bin 0 -> 19544 bytes
 .../fonts/OpenSans-Bold-webfont.svg                | 1830 ++++
 .../fonts/OpenSans-Bold-webfont.woff               |  Bin 0 -> 22432 bytes
 .../fonts/OpenSans-BoldItalic-webfont.eot          |  Bin 0 -> 20133 bytes
 .../fonts/OpenSans-BoldItalic-webfont.svg          | 1830 ++++
 .../fonts/OpenSans-BoldItalic-webfont.woff         |  Bin 0 -> 23048 bytes
 .../fonts/OpenSans-Italic-webfont.eot              |  Bin 0 -> 20265 bytes
 .../fonts/OpenSans-Italic-webfont.svg              | 1830 ++++
 .../fonts/OpenSans-Italic-webfont.woff             |  Bin 0 -> 23188 bytes
 .../fonts/OpenSans-Light-webfont.eot               |  Bin 0 -> 19514 bytes
 .../fonts/OpenSans-Light-webfont.svg               | 1831 ++++
 .../fonts/OpenSans-Light-webfont.woff              |  Bin 0 -> 22248 bytes
 .../fonts/OpenSans-LightItalic-webfont.eot         |  Bin 0 -> 20535 bytes
 .../fonts/OpenSans-LightItalic-webfont.svg         | 1835 ++++
 .../fonts/OpenSans-LightItalic-webfont.woff        |  Bin 0 -> 23400 bytes
 .../fonts/OpenSans-Regular-webfont.eot             |  Bin 0 -> 19836 bytes
 .../fonts/OpenSans-Regular-webfont.svg             | 1831 ++++
 .../fonts/OpenSans-Regular-webfont.woff            |  Bin 0 -> 22660 bytes
 content/doc/1.1.0/guacamole-common-js/index.html   |   75 +
 .../guacamole-common-js/scripts/linenumber.js      |   25 +
 .../scripts/prettify/Apache-License-2.0.txt        |  202 +
 .../scripts/prettify/lang-css.js                   |    2 +
 .../scripts/prettify/prettify.js                   |   28 +
 .../guacamole-common-js/styles/jsdoc-default.css   |  358 +
 .../guacamole-common-js/styles/prettify-jsdoc.css  |  111 +
 .../styles/prettify-tomorrow.css                   |  132 +
 .../1.1.0/guacamole-common/allclasses-frame.html   |   77 +
 .../1.1.0/guacamole-common/allclasses-noframe.html |   77 +
 .../1.1.0/guacamole-common/constant-values.html    |  200 +
 .../1.1.0/guacamole-common/deprecated-list.html    |  136 +
 content/doc/1.1.0/guacamole-common/help-doc.html   |  241 +
 content/doc/1.1.0/guacamole-common/index-all.html  | 1459 ++++
 content/doc/1.1.0/guacamole-common/index.html      |   76 +
 .../guacamole/GuacamoleClientBadTypeException.html |  389 +
 .../apache/guacamole/GuacamoleClientException.html |  389 +
 .../guacamole/GuacamoleClientOverrunException.html |  391 +
 .../guacamole/GuacamoleClientTimeoutException.html |  388 +
 .../guacamole/GuacamoleClientTooManyException.html |  390 +
 .../GuacamoleConnectionClosedException.html        |  391 +
 .../org/apache/guacamole/GuacamoleException.html   |  419 +
 .../GuacamoleResourceClosedException.html          |  389 +
 .../GuacamoleResourceConflictException.html        |  390 +
 .../GuacamoleResourceNotFoundException.html        |  391 +
 .../guacamole/GuacamoleSecurityException.html      |  393 +
 .../guacamole/GuacamoleServerBusyException.html    |  389 +
 .../apache/guacamole/GuacamoleServerException.html |  389 +
 .../guacamole/GuacamoleSessionClosedException.html |  389 +
 .../GuacamoleSessionConflictException.html         |  389 +
 .../GuacamoleSessionTimeoutException.html          |  389 +
 .../guacamole/GuacamoleUnauthorizedException.html  |  395 +
 .../guacamole/GuacamoleUnsupportedException.html   |  389 +
 .../guacamole/GuacamoleUpstreamException.html      |  390 +
 .../GuacamoleUpstreamNotFoundException.html        |  389 +
 .../GuacamoleUpstreamTimeoutException.html         |  391 +
 .../GuacamoleUpstreamUnavailableException.html     |  393 +
 .../class-use/GuacamoleClientBadTypeException.html |  136 +
 .../class-use/GuacamoleClientException.html        |  240 +
 .../class-use/GuacamoleClientOverrunException.html |  136 +
 .../class-use/GuacamoleClientTimeoutException.html |  136 +
 .../class-use/GuacamoleClientTooManyException.html |  136 +
 .../GuacamoleConnectionClosedException.html        |  136 +
 .../guacamole/class-use/GuacamoleException.html    |  684 ++
 .../GuacamoleResourceClosedException.html          |  136 +
 .../GuacamoleResourceConflictException.html        |  136 +
 .../GuacamoleResourceNotFoundException.html        |  136 +
 .../class-use/GuacamoleSecurityException.html      |  184 +
 .../class-use/GuacamoleServerBusyException.html    |  136 +
 .../class-use/GuacamoleServerException.html        |  197 +
 .../class-use/GuacamoleSessionClosedException.html |  136 +
 .../GuacamoleSessionConflictException.html         |  136 +
 .../GuacamoleSessionTimeoutException.html          |  136 +
 .../class-use/GuacamoleUnauthorizedException.html  |  136 +
 .../class-use/GuacamoleUnsupportedException.html   |  136 +
 .../class-use/GuacamoleUpstreamException.html      |  252 +
 .../GuacamoleUpstreamNotFoundException.html        |  136 +
 .../GuacamoleUpstreamTimeoutException.html         |  136 +
 .../GuacamoleUpstreamUnavailableException.html     |  136 +
 .../org/apache/guacamole/io/GuacamoleReader.html   |  312 +
 .../org/apache/guacamole/io/GuacamoleWriter.html   |  312 +
 .../apache/guacamole/io/ReaderGuacamoleReader.html |  381 +
 .../apache/guacamole/io/WriterGuacamoleWriter.html |  381 +
 .../guacamole/io/class-use/GuacamoleReader.html    |  299 +
 .../guacamole/io/class-use/GuacamoleWriter.html    |  299 +
 .../io/class-use/ReaderGuacamoleReader.html        |  136 +
 .../io/class-use/WriterGuacamoleWriter.html        |  136 +
 .../org/apache/guacamole/io/package-frame.html     |   37 +
 .../org/apache/guacamole/io/package-summary.html   |  198 +
 .../org/apache/guacamole/io/package-tree.html      |  155 +
 .../org/apache/guacamole/io/package-use.html       |  241 +
 .../guacamole/net/AbstractGuacamoleTunnel.html     |  506 ++
 .../guacamole/net/DelegatingGuacamoleTunnel.html   |  549 ++
 .../org/apache/guacamole/net/GuacamoleSocket.html  |  320 +
 .../org/apache/guacamole/net/GuacamoleTunnel.html  |  489 ++
 .../apache/guacamole/net/InetGuacamoleSocket.html  |  402 +
 .../apache/guacamole/net/SSLGuacamoleSocket.html   |  402 +
 .../guacamole/net/SimpleGuacamoleTunnel.html       |  356 +
 .../net/class-use/AbstractGuacamoleTunnel.html     |  181 +
 .../net/class-use/DelegatingGuacamoleTunnel.html   |  136 +
 .../guacamole/net/class-use/GuacamoleSocket.html   |  318 +
 .../guacamole/net/class-use/GuacamoleTunnel.html   |  292 +
 .../net/class-use/InetGuacamoleSocket.html         |  136 +
 .../net/class-use/SSLGuacamoleSocket.html          |  136 +
 .../net/class-use/SimpleGuacamoleTunnel.html       |  136 +
 .../org/apache/guacamole/net/package-frame.html    |   40 +
 .../org/apache/guacamole/net/package-summary.html  |  219 +
 .../org/apache/guacamole/net/package-tree.html     |  161 +
 .../org/apache/guacamole/net/package-use.html      |  256 +
 .../org/apache/guacamole/package-frame.html        |   52 +
 .../org/apache/guacamole/package-summary.html      |  318 +
 .../org/apache/guacamole/package-tree.html         |  193 +
 .../org/apache/guacamole/package-use.html          |  326 +
 .../protocol/ConfiguredGuacamoleSocket.html        |  516 ++
 .../protocol/FailoverGuacamoleSocket.html          |  452 +
 .../protocol/FilteredGuacamoleReader.html          |  387 +
 .../protocol/FilteredGuacamoleSocket.html          |  404 +
 .../protocol/FilteredGuacamoleWriter.html          |  387 +
 .../protocol/GuacamoleClientInformation.html       |  510 ++
 .../guacamole/protocol/GuacamoleConfiguration.html |  529 ++
 .../apache/guacamole/protocol/GuacamoleFilter.html |  256 +
 .../guacamole/protocol/GuacamoleInstruction.html   |  380 +
 .../apache/guacamole/protocol/GuacamoleParser.html |  479 ++
 .../protocol/GuacamoleProtocolCapability.html      |  413 +
 .../protocol/GuacamoleProtocolVersion.html         |  532 ++
 .../apache/guacamole/protocol/GuacamoleStatus.html |  759 ++
 .../class-use/ConfiguredGuacamoleSocket.html       |  136 +
 .../class-use/FailoverGuacamoleSocket.html         |  136 +
 .../class-use/FilteredGuacamoleReader.html         |  136 +
 .../class-use/FilteredGuacamoleSocket.html         |  136 +
 .../class-use/FilteredGuacamoleWriter.html         |  136 +
 .../class-use/GuacamoleClientInformation.html      |  182 +
 .../protocol/class-use/GuacamoleConfiguration.html |  213 +
 .../protocol/class-use/GuacamoleFilter.html        |  196 +
 .../protocol/class-use/GuacamoleInstruction.html   |  262 +
 .../protocol/class-use/GuacamoleParser.html        |  136 +
 .../class-use/GuacamoleProtocolCapability.html     |  187 +
 .../class-use/GuacamoleProtocolVersion.html        |  241 +
 .../protocol/class-use/GuacamoleStatus.html        |  306 +
 .../apache/guacamole/protocol/package-frame.html   |   49 +
 .../apache/guacamole/protocol/package-summary.html |  270 +
 .../apache/guacamole/protocol/package-tree.html    |  175 +
 .../org/apache/guacamole/protocol/package-use.html |  258 +
 .../servlet/GuacamoleHTTPTunnelServlet.html        |  606 ++
 .../class-use/GuacamoleHTTPTunnelServlet.html      |  136 +
 .../apache/guacamole/servlet/package-frame.html    |   31 +
 .../apache/guacamole/servlet/package-summary.html  |  168 +
 .../org/apache/guacamole/servlet/package-tree.html |  157 +
 .../org/apache/guacamole/servlet/package-use.html  |  136 +
 .../GuacamoleWebSocketTunnelEndpoint.html          |  369 +
 .../GuacamoleWebSocketTunnelEndpoint.html          |  136 +
 .../apache/guacamole/websocket/package-frame.html  |   31 +
 .../guacamole/websocket/package-summary.html       |  157 +
 .../apache/guacamole/websocket/package-tree.html   |  153 +
 .../apache/guacamole/websocket/package-use.html    |  136 +
 .../doc/1.1.0/guacamole-common/overview-frame.html |   37 +
 .../1.1.0/guacamole-common/overview-summary.html   |  184 +
 .../doc/1.1.0/guacamole-common/overview-tree.html  |  253 +
 content/doc/1.1.0/guacamole-common/package-list    |    6 +
 content/doc/1.1.0/guacamole-common/script.js       |   30 +
 .../1.1.0/guacamole-common/serialized-form.html    |  318 +
 content/doc/1.1.0/guacamole-common/stylesheet.css  |  574 ++
 .../doc/1.1.0/guacamole-ext/allclasses-frame.html  |  149 +
 .../1.1.0/guacamole-ext/allclasses-noframe.html    |  149 +
 .../doc/1.1.0/guacamole-ext/constant-values.html   |  280 +
 .../doc/1.1.0/guacamole-ext/deprecated-list.html   |  298 +
 content/doc/1.1.0/guacamole-ext/help-doc.html      |  241 +
 content/doc/1.1.0/guacamole-ext/index-all.html     | 3432 ++++++++
 content/doc/1.1.0/guacamole-ext/index.html         |   76 +
 .../apache/guacamole/environment/Environment.html  |  504 ++
 .../guacamole/environment/LocalEnvironment.html    |  530 ++
 .../environment/class-use/Environment.html         |  180 +
 .../environment/class-use/LocalEnvironment.html    |  136 +
 .../guacamole/environment/package-frame.html       |   35 +
 .../guacamole/environment/package-summary.html     |  176 +
 .../apache/guacamole/environment/package-tree.html |  153 +
 .../apache/guacamole/environment/package-use.html  |  172 +
 .../org/apache/guacamole/form/BooleanField.html    |  293 +
 .../org/apache/guacamole/form/DateField.html       |  402 +
 .../org/apache/guacamole/form/EmailField.html      |  284 +
 .../org/apache/guacamole/form/EnumField.html       |  288 +
 .../org/apache/guacamole/form/Field.Type.html      |  522 ++
 .../org/apache/guacamole/form/Field.html           |  473 +
 .../org/apache/guacamole/form/FieldOption.html     |  376 +
 .../org/apache/guacamole/form/Form.html            |  382 +
 .../org/apache/guacamole/form/LanguageField.html   |  334 +
 .../org/apache/guacamole/form/MultilineField.html  |  284 +
 .../org/apache/guacamole/form/NumericField.html    |  356 +
 .../org/apache/guacamole/form/PasswordField.html   |  285 +
 .../guacamole/form/TerminalColorSchemeField.html   |  286 +
 .../org/apache/guacamole/form/TextField.html       |  354 +
 .../org/apache/guacamole/form/TimeField.html       |  402 +
 .../org/apache/guacamole/form/TimeZoneField.html   |  332 +
 .../org/apache/guacamole/form/UsernameField.html   |  285 +
 .../guacamole/form/class-use/BooleanField.html     |  136 +
 .../apache/guacamole/form/class-use/DateField.html |  136 +
 .../guacamole/form/class-use/EmailField.html       |  136 +
 .../apache/guacamole/form/class-use/EnumField.html |  136 +
 .../guacamole/form/class-use/Field.Type.html       |  136 +
 .../org/apache/guacamole/form/class-use/Field.html |  406 +
 .../guacamole/form/class-use/FieldOption.html      |  136 +
 .../org/apache/guacamole/form/class-use/Form.html  |  341 +
 .../guacamole/form/class-use/LanguageField.html    |  136 +
 .../guacamole/form/class-use/MultilineField.html   |  136 +
 .../guacamole/form/class-use/NumericField.html     |  136 +
 .../guacamole/form/class-use/PasswordField.html    |  136 +
 .../form/class-use/TerminalColorSchemeField.html   |  136 +
 .../apache/guacamole/form/class-use/TextField.html |  136 +
 .../apache/guacamole/form/class-use/TimeField.html |  136 +
 .../guacamole/form/class-use/TimeZoneField.html    |  136 +
 .../guacamole/form/class-use/UsernameField.html    |  136 +
 .../org/apache/guacamole/form/package-frame.html   |   47 +
 .../org/apache/guacamole/form/package-summary.html |  267 +
 .../org/apache/guacamole/form/package-tree.html    |  168 +
 .../org/apache/guacamole/form/package-use.html     |  242 +
 .../apache/guacamole/language/Translatable.html    |  247 +
 .../guacamole/language/TranslatableMessage.html    |  355 +
 .../guacamole/language/class-use/Translatable.html |  136 +
 .../language/class-use/TranslatableMessage.html    |  180 +
 .../apache/guacamole/language/package-frame.html   |   35 +
 .../apache/guacamole/language/package-summary.html |  177 +
 .../apache/guacamole/language/package-tree.html    |  153 +
 .../org/apache/guacamole/language/package-use.html |  173 +
 .../net/auth/AbstractActiveConnection.html         |  608 ++
 .../net/auth/AbstractAuthenticatedUser.html        |  376 +
 .../net/auth/AbstractAuthenticationProvider.html   |  660 ++
 .../guacamole/net/auth/AbstractConnection.html     |  500 ++
 .../net/auth/AbstractConnectionGroup.html          |  479 ++
 .../guacamole/net/auth/AbstractIdentifiable.html   |  365 +
 .../guacamole/net/auth/AbstractSharingProfile.html |  527 ++
 .../apache/guacamole/net/auth/AbstractUser.html    |  773 ++
 .../guacamole/net/auth/AbstractUserContext.html    |  865 ++
 .../guacamole/net/auth/AbstractUserGroup.html      |  681 ++
 .../guacamole/net/auth/ActiveConnection.html       |  600 ++
 .../apache/guacamole/net/auth/ActivityRecord.html  |  337 +
 .../auth/ActivityRecordSet.SortableProperty.html   |  352 +
 .../guacamole/net/auth/ActivityRecordSet.html      |  381 +
 .../org/apache/guacamole/net/auth/Attributes.html  |  283 +
 .../guacamole/net/auth/AuthenticatedUser.html      |  375 +
 .../guacamole/net/auth/AuthenticationProvider.html |  551 ++
 .../org/apache/guacamole/net/auth/Connectable.html |  335 +
 .../org/apache/guacamole/net/auth/Connection.html  |  468 +
 .../guacamole/net/auth/ConnectionGroup.Type.html   |  371 +
 .../apache/guacamole/net/auth/ConnectionGroup.html |  451 +
 .../guacamole/net/auth/ConnectionRecord.html       |  331 +
 .../guacamole/net/auth/ConnectionRecordSet.html    |  229 +
 .../org/apache/guacamole/net/auth/Credentials.html |  567 ++
 .../guacamole/net/auth/DecoratingDirectory.html    |  519 ++
 .../guacamole/net/auth/DelegatingConnection.html   |  758 ++
 .../net/auth/DelegatingConnectionGroup.html        |  736 ++
 .../guacamole/net/auth/DelegatingDirectory.html    |  502 ++
 .../net/auth/DelegatingSharingProfile.html         |  576 ++
 .../apache/guacamole/net/auth/DelegatingUser.html  |  795 ++
 .../guacamole/net/auth/DelegatingUserContext.html  |  838 ++
 .../guacamole/net/auth/DelegatingUserGroup.html    |  705 ++
 .../org/apache/guacamole/net/auth/Directory.html   |  402 +
 ...acamoleProxyConfiguration.EncryptionMethod.html |  364 +
 .../net/auth/GuacamoleProxyConfiguration.html      |  402 +
 .../apache/guacamole/net/auth/Identifiable.html    |  273 +
 .../org/apache/guacamole/net/auth/Permissions.html |  409 +
 .../guacamole/net/auth/RelatedObjectSet.html       |  350 +
 .../org/apache/guacamole/net/auth/Shareable.html   |  272 +
 .../apache/guacamole/net/auth/SharingProfile.html  |  387 +
 .../net/auth/TokenInjectingConnection.html         |  346 +
 .../net/auth/TokenInjectingConnectionGroup.html    |  361 +
 .../net/auth/TokenInjectingUserContext.html        |  454 +
 .../apache/guacamole/net/auth/User.Attribute.html  |  346 +
 .../org/apache/guacamole/net/auth/User.html        |  423 +
 .../org/apache/guacamole/net/auth/UserContext.html |  696 ++
 .../org/apache/guacamole/net/auth/UserGroup.html   |  337 +
 .../auth/class-use/AbstractActiveConnection.html   |  136 +
 .../auth/class-use/AbstractAuthenticatedUser.html  |  136 +
 .../class-use/AbstractAuthenticationProvider.html  |  183 +
 .../net/auth/class-use/AbstractConnection.html     |  183 +
 .../auth/class-use/AbstractConnectionGroup.html    |  184 +
 .../net/auth/class-use/AbstractIdentifiable.html   |  265 +
 .../net/auth/class-use/AbstractSharingProfile.html |  136 +
 .../guacamole/net/auth/class-use/AbstractUser.html |  182 +
 .../net/auth/class-use/AbstractUserContext.html    |  183 +
 .../net/auth/class-use/AbstractUserGroup.html      |  183 +
 .../net/auth/class-use/ActiveConnection.html       |  211 +
 .../net/auth/class-use/ActivityRecord.html         |  270 +
 .../ActivityRecordSet.SortableProperty.html        |  239 +
 .../net/auth/class-use/ActivityRecordSet.html      |  304 +
 .../guacamole/net/auth/class-use/Attributes.html   |  351 +
 .../net/auth/class-use/AuthenticatedUser.html      |  462 +
 .../net/auth/class-use/AuthenticationProvider.html |  283 +
 .../guacamole/net/auth/class-use/Connectable.html  |  291 +
 .../guacamole/net/auth/class-use/Connection.html   |  377 +
 .../net/auth/class-use/ConnectionGroup.Type.html   |  225 +
 .../net/auth/class-use/ConnectionGroup.html        |  386 +
 .../net/auth/class-use/ConnectionRecord.html       |  234 +
 .../net/auth/class-use/ConnectionRecordSet.html    |  213 +
 .../guacamole/net/auth/class-use/Credentials.html  |  418 +
 .../net/auth/class-use/DecoratingDirectory.html    |  136 +
 .../net/auth/class-use/DelegatingConnection.html   |  183 +
 .../auth/class-use/DelegatingConnectionGroup.html  |  183 +
 .../net/auth/class-use/DelegatingDirectory.html    |  182 +
 .../auth/class-use/DelegatingSharingProfile.html   |  136 +
 .../net/auth/class-use/DelegatingUser.html         |  136 +
 .../net/auth/class-use/DelegatingUserContext.html  |  183 +
 .../net/auth/class-use/DelegatingUserGroup.html    |  136 +
 .../guacamole/net/auth/class-use/Directory.html    |  418 +
 ...acamoleProxyConfiguration.EncryptionMethod.html |  210 +
 .../class-use/GuacamoleProxyConfiguration.html     |  183 +
 .../guacamole/net/auth/class-use/Identifiable.html |  446 +
 .../guacamole/net/auth/class-use/Permissions.html  |  284 +
 .../net/auth/class-use/RelatedObjectSet.html       |  287 +
 .../guacamole/net/auth/class-use/Shareable.html    |  198 +
 .../net/auth/class-use/SharingProfile.html         |  248 +
 .../auth/class-use/TokenInjectingConnection.html   |  136 +
 .../class-use/TokenInjectingConnectionGroup.html   |  136 +
 .../auth/class-use/TokenInjectingUserContext.html  |  136 +
 .../net/auth/class-use/User.Attribute.html         |  136 +
 .../apache/guacamole/net/auth/class-use/User.html  |  314 +
 .../guacamole/net/auth/class-use/UserContext.html  |  435 +
 .../guacamole/net/auth/class-use/UserGroup.html    |  276 +
 .../net/auth/credentials/CredentialsInfo.html      |  400 +
 .../credentials/GuacamoleCredentialsException.html |  419 +
 .../GuacamoleInsufficientCredentialsException.html |  388 +
 .../GuacamoleInvalidCredentialsException.html      |  386 +
 .../net/auth/credentials/UserCredentials.html      |  585 ++
 .../credentials/class-use/CredentialsInfo.html     |  302 +
 .../class-use/GuacamoleCredentialsException.html   |  186 +
 .../GuacamoleInsufficientCredentialsException.html |  136 +
 .../GuacamoleInvalidCredentialsException.html      |  136 +
 .../credentials/class-use/UserCredentials.html     |  182 +
 .../net/auth/credentials/package-frame.html        |   38 +
 .../net/auth/credentials/package-summary.html      |  194 +
 .../net/auth/credentials/package-tree.html         |  183 +
 .../net/auth/credentials/package-use.html          |  201 +
 .../apache/guacamole/net/auth/package-frame.html   |   83 +
 .../apache/guacamole/net/auth/package-summary.html |  507 ++
 .../apache/guacamole/net/auth/package-tree.html    |  256 +
 .../org/apache/guacamole/net/auth/package-use.html |  587 ++
 .../net/auth/permission/ObjectPermission.Type.html |  395 +
 .../net/auth/permission/ObjectPermission.html      |  391 +
 .../net/auth/permission/ObjectPermissionSet.html   |  488 ++
 .../guacamole/net/auth/permission/Permission.html  |  251 +
 .../net/auth/permission/PermissionSet.html         |  311 +
 .../net/auth/permission/SystemPermission.Type.html |  429 +
 .../net/auth/permission/SystemPermission.html      |  364 +
 .../net/auth/permission/SystemPermissionSet.html   |  432 +
 .../class-use/ObjectPermission.Type.html           |  323 +
 .../permission/class-use/ObjectPermission.html     |  259 +
 .../permission/class-use/ObjectPermissionSet.html  |  412 +
 .../net/auth/permission/class-use/Permission.html  |  204 +
 .../auth/permission/class-use/PermissionSet.html   |  224 +
 .../class-use/SystemPermission.Type.html           |  267 +
 .../permission/class-use/SystemPermission.html     |  259 +
 .../permission/class-use/SystemPermissionSet.html  |  258 +
 .../net/auth/permission/package-frame.html         |   44 +
 .../net/auth/permission/package-summary.html       |  235 +
 .../net/auth/permission/package-tree.html          |  173 +
 .../guacamole/net/auth/permission/package-use.html |  301 +
 .../net/auth/simple/SimpleActivityRecordSet.html   |  431 +
 .../auth/simple/SimpleAuthenticationProvider.html  |  420 +
 .../net/auth/simple/SimpleConnection.html          |  673 ++
 .../net/auth/simple/SimpleConnectionDirectory.html |  354 +
 .../net/auth/simple/SimpleConnectionGroup.html     |  537 ++
 .../simple/SimpleConnectionGroupDirectory.html     |  356 +
 .../net/auth/simple/SimpleConnectionRecordSet.html |  443 +
 .../guacamole/net/auth/simple/SimpleDirectory.html |  616 ++
 .../net/auth/simple/SimpleObjectPermissionSet.html |  622 ++
 .../net/auth/simple/SimpleRelatedObjectSet.html    |  432 +
 .../net/auth/simple/SimpleSystemPermissionSet.html |  514 ++
 .../guacamole/net/auth/simple/SimpleUser.html      |  528 ++
 .../net/auth/simple/SimpleUserContext.html         |  516 ++
 .../net/auth/simple/SimpleUserDirectory.html       |  282 +
 .../guacamole/net/auth/simple/SimpleUserGroup.html |  309 +
 .../simple/class-use/SimpleActivityRecordSet.html  |  136 +
 .../class-use/SimpleAuthenticationProvider.html    |  136 +
 .../auth/simple/class-use/SimpleConnection.html    |  136 +
 .../class-use/SimpleConnectionDirectory.html       |  136 +
 .../simple/class-use/SimpleConnectionGroup.html    |  136 +
 .../class-use/SimpleConnectionGroupDirectory.html  |  136 +
 .../class-use/SimpleConnectionRecordSet.html       |  136 +
 .../net/auth/simple/class-use/SimpleDirectory.html |  200 +
 .../class-use/SimpleObjectPermissionSet.html       |  136 +
 .../simple/class-use/SimpleRelatedObjectSet.html   |  136 +
 .../class-use/SimpleSystemPermissionSet.html       |  136 +
 .../net/auth/simple/class-use/SimpleUser.html      |  136 +
 .../auth/simple/class-use/SimpleUserContext.html   |  136 +
 .../auth/simple/class-use/SimpleUserDirectory.html |  136 +
 .../net/auth/simple/class-use/SimpleUserGroup.html |  136 +
 .../guacamole/net/auth/simple/package-frame.html   |   45 +
 .../guacamole/net/auth/simple/package-summary.html |  264 +
 .../guacamole/net/auth/simple/package-tree.html    |  194 +
 .../guacamole/net/auth/simple/package-use.html     |  176 +
 .../net/event/AuthenticationFailureEvent.html      |  311 +
 .../net/event/AuthenticationSuccessEvent.html      |  345 +
 .../guacamole/net/event/CredentialEvent.html       |  247 +
 .../guacamole/net/event/TunnelCloseEvent.html      |  375 +
 .../guacamole/net/event/TunnelConnectEvent.html    |  375 +
 .../apache/guacamole/net/event/TunnelEvent.html    |  246 +
 .../org/apache/guacamole/net/event/UserEvent.html  |  249 +
 .../class-use/AuthenticationFailureEvent.html      |  183 +
 .../class-use/AuthenticationSuccessEvent.html      |  183 +
 .../net/event/class-use/CredentialEvent.html       |  201 +
 .../net/event/class-use/TunnelCloseEvent.html      |  182 +
 .../net/event/class-use/TunnelConnectEvent.html    |  182 +
 .../guacamole/net/event/class-use/TunnelEvent.html |  187 +
 .../guacamole/net/event/class-use/UserEvent.html   |  194 +
 .../listener/AuthenticationFailureListener.html    |  258 +
 .../listener/AuthenticationSuccessListener.html    |  262 +
 .../guacamole/net/event/listener/Listener.html     |  255 +
 .../net/event/listener/TunnelCloseListener.html    |  259 +
 .../net/event/listener/TunnelConnectListener.html  |  260 +
 .../class-use/AuthenticationFailureListener.html   |  136 +
 .../class-use/AuthenticationSuccessListener.html   |  136 +
 .../net/event/listener/class-use/Listener.html     |  136 +
 .../listener/class-use/TunnelCloseListener.html    |  136 +
 .../listener/class-use/TunnelConnectListener.html  |  136 +
 .../net/event/listener/package-frame.html          |   35 +
 .../net/event/listener/package-summary.html        |  195 +
 .../guacamole/net/event/listener/package-tree.html |  149 +
 .../guacamole/net/event/listener/package-use.html  |  136 +
 .../apache/guacamole/net/event/package-frame.html  |   40 +
 .../guacamole/net/event/package-summary.html       |  224 +
 .../apache/guacamole/net/event/package-tree.html   |  158 +
 .../apache/guacamole/net/event/package-use.html    |  227 +
 .../properties/BooleanGuacamoleProperty.html       |  315 +
 .../properties/FileGuacamoleProperty.html          |  314 +
 .../guacamole/properties/GuacamoleProperty.html    |  281 +
 .../properties/IntegerGuacamoleProperty.html       |  314 +
 .../properties/LongGuacamoleProperty.html          |  314 +
 .../properties/StringGuacamoleProperty.html        |  314 +
 .../class-use/BooleanGuacamoleProperty.html        |  178 +
 .../class-use/FileGuacamoleProperty.html           |  136 +
 .../properties/class-use/GuacamoleProperty.html    |  258 +
 .../class-use/IntegerGuacamoleProperty.html        |  178 +
 .../class-use/LongGuacamoleProperty.html           |  136 +
 .../class-use/StringGuacamoleProperty.html         |  179 +
 .../apache/guacamole/properties/package-frame.html |   39 +
 .../guacamole/properties/package-summary.html      |  209 +
 .../apache/guacamole/properties/package-tree.html  |  157 +
 .../apache/guacamole/properties/package-use.html   |  212 +
 .../apache/guacamole/protocols/ProtocolInfo.html   |  492 ++
 .../protocols/class-use/ProtocolInfo.html          |  202 +
 .../apache/guacamole/protocols/package-frame.html  |   31 +
 .../guacamole/protocols/package-summary.html       |  157 +
 .../apache/guacamole/protocols/package-tree.html   |  149 +
 .../apache/guacamole/protocols/package-use.html    |  172 +
 .../org/apache/guacamole/token/StandardTokens.html |  495 ++
 .../org/apache/guacamole/token/TokenFilter.html    |  465 +
 .../org/apache/guacamole/token/TokenName.html      |  298 +
 .../guacamole/token/class-use/StandardTokens.html  |  136 +
 .../guacamole/token/class-use/TokenFilter.html     |  199 +
 .../guacamole/token/class-use/TokenName.html       |  136 +
 .../org/apache/guacamole/token/package-frame.html  |   33 +
 .../apache/guacamole/token/package-summary.html    |  170 +
 .../org/apache/guacamole/token/package-tree.html   |  151 +
 .../org/apache/guacamole/token/package-use.html    |  172 +
 .../org/apache/guacamole/xml/DocumentHandler.html  |  382 +
 .../org/apache/guacamole/xml/TagHandler.html       |  303 +
 .../guacamole/xml/class-use/DocumentHandler.html   |  136 +
 .../apache/guacamole/xml/class-use/TagHandler.html |  196 +
 .../org/apache/guacamole/xml/package-frame.html    |   35 +
 .../org/apache/guacamole/xml/package-summary.html  |  187 +
 .../org/apache/guacamole/xml/package-tree.html     |  157 +
 .../org/apache/guacamole/xml/package-use.html      |  175 +
 .../doc/1.1.0/guacamole-ext/overview-frame.html    |   44 +
 .../doc/1.1.0/guacamole-ext/overview-summary.html  |  223 +
 content/doc/1.1.0/guacamole-ext/overview-tree.html |  402 +
 content/doc/1.1.0/guacamole-ext/package-list       |   13 +
 content/doc/1.1.0/guacamole-ext/script.js          |   30 +
 .../doc/1.1.0/guacamole-ext/serialized-form.html   |  215 +
 content/doc/1.1.0/guacamole-ext/stylesheet.css     |  574 ++
 content/doc/1.1.0/gug/adhoc-connections.html       |   69 +
 content/doc/1.1.0/gug/administration.html          |  163 +
 content/doc/1.1.0/gug/appendices.html              |   21 +
 content/doc/1.1.0/gug/book-index.html              |   21 +
 content/doc/1.1.0/gug/cas-auth.html                |   59 +
 content/doc/1.1.0/gug/configuring-guacamole.html   | 2489 ++++++
 content/doc/1.1.0/gug/custom-auth.html             |  383 +
 content/doc/1.1.0/gug/custom-protocols.html        |  654 ++
 content/doc/1.1.0/gug/developers-guide.html        |   21 +
 content/doc/1.1.0/gug/duo-auth.html                |  102 +
 content/doc/1.1.0/gug/event-listeners.html         |  292 +
 content/doc/1.1.0/gug/faq.html                     |   86 +
 content/doc/1.1.0/gug/guacamole-architecture.html  |   83 +
 content/doc/1.1.0/gug/guacamole-common-js.html     |  263 +
 content/doc/1.1.0/gug/guacamole-common.html        |  141 +
 content/doc/1.1.0/gug/guacamole-docker.html        |  413 +
 content/doc/1.1.0/gug/guacamole-ext.html           |  457 +
 content/doc/1.1.0/gug/guacamole-protocol.html      |  193 +
 content/doc/1.1.0/gug/gug.css                      |  179 +
 content/doc/1.1.0/gug/header-auth.html             |   54 +
 content/doc/1.1.0/gug/images/duo-add-guacamole.png |  Bin 0 -> 7156 bytes
 content/doc/1.1.0/gug/images/duo-auth-factor-1.png |  Bin 0 -> 12418 bytes
 content/doc/1.1.0/gug/images/duo-auth-factor-2.png |  Bin 0 -> 28876 bytes
 content/doc/1.1.0/gug/images/duo-copy-details.png  |  Bin 0 -> 19979 bytes
 .../doc/1.1.0/gug/images/duo-rename-guacamole.png  |  Bin 0 -> 13016 bytes
 content/doc/1.1.0/gug/images/edit-connection.png   |  Bin 0 -> 119196 bytes
 .../1.1.0/gug/images/edit-group-memberships.png    |  Bin 0 -> 31653 bytes
 content/doc/1.1.0/gug/images/edit-group.png        |  Bin 0 -> 29614 bytes
 .../doc/1.1.0/gug/images/edit-sharing-profile.png  |  Bin 0 -> 22420 bytes
 content/doc/1.1.0/gug/images/edit-user-group.png   |  Bin 0 -> 129269 bytes
 .../doc/1.1.0/gug/images/edit-user-membership.png  |  Bin 0 -> 8415 bytes
 content/doc/1.1.0/gug/images/edit-user.png         |  Bin 0 -> 72176 bytes
 content/doc/1.1.0/gug/images/file-browser.png      |  Bin 0 -> 97706 bytes
 content/doc/1.1.0/gug/images/file-transfers.png    |  Bin 0 -> 9586 bytes
 content/doc/1.1.0/gug/images/guac-arch.png         |  Bin 0 -> 51821 bytes
 .../doc/1.1.0/gug/images/guac-menu-disconnect.png  |  Bin 0 -> 19486 bytes
 .../doc/1.1.0/gug/images/guac-menu-share-link.png  |  Bin 0 -> 19965 bytes
 content/doc/1.1.0/gug/images/guac-menu-share.png   |  Bin 0 -> 8726 bytes
 .../gug/images/guacamole-client-interface.png      |  Bin 0 -> 309368 bytes
 .../1.1.0/gug/images/guacamole-drive-download.png  |  Bin 0 -> 19149 bytes
 content/doc/1.1.0/gug/images/guacamole-drive.png   |  Bin 0 -> 27334 bytes
 .../doc/1.1.0/gug/images/guacamole-home-screen.png |  Bin 0 -> 77377 bytes
 .../doc/1.1.0/gug/images/guacamole-preferences.png |  Bin 0 -> 161522 bytes
 .../gug/images/guacamole-settings-sections.png     |  Bin 0 -> 11928 bytes
 content/doc/1.1.0/gug/images/manage-button.png     |  Bin 0 -> 16773 bytes
 .../doc/1.1.0/gug/images/manage-connections.png    |  Bin 0 -> 87829 bytes
 content/doc/1.1.0/gug/images/manage-groups.png     |  Bin 0 -> 33629 bytes
 content/doc/1.1.0/gug/images/manage-history.png    |  Bin 0 -> 148440 bytes
 content/doc/1.1.0/gug/images/manage-sessions.png   |  Bin 0 -> 61738 bytes
 content/doc/1.1.0/gug/images/manage-users.png      |  Bin 0 -> 33353 bytes
 .../1.1.0/gug/images/session-filter-example-1.png  |  Bin 0 -> 3038 bytes
 .../1.1.0/gug/images/session-filter-example-2.png  |  Bin 0 -> 2055 bytes
 .../doc/1.1.0/gug/images/totp-auth-factor-1.png    |  Bin 0 -> 12418 bytes
 .../doc/1.1.0/gug/images/totp-auth-factor-2.png    |  Bin 0 -> 14088 bytes
 .../doc/1.1.0/gug/images/totp-enroll-detail.png    |  Bin 0 -> 42801 bytes
 content/doc/1.1.0/gug/images/totp-enroll.png       |  Bin 0 -> 33722 bytes
 content/doc/1.1.0/gug/images/touchpad.png          |  Bin 0 -> 16504 bytes
 content/doc/1.1.0/gug/images/touchscreen.png       |  Bin 0 -> 9681 bytes
 content/doc/1.1.0/gug/index.html                   |   29 +
 content/doc/1.1.0/gug/installing-guacamole.html    |  454 +
 content/doc/1.1.0/gug/jdbc-auth.html               |  920 ++
 content/doc/1.1.0/gug/ldap-auth.html               |  315 +
 content/doc/1.1.0/gug/libguac.html                 |  263 +
 content/doc/1.1.0/gug/openid-auth.html             |   98 +
 content/doc/1.1.0/gug/preface.html                 |   92 +
 content/doc/1.1.0/gug/protocol-reference.html      |  338 +
 content/doc/1.1.0/gug/proxying-guacamole.html      |  220 +
 content/doc/1.1.0/gug/radius-auth.html             |  137 +
 content/doc/1.1.0/gug/totp-auth.html               |   94 +
 content/doc/1.1.0/gug/troubleshooting.html         |  407 +
 content/doc/1.1.0/gug/users-guide.html             |   21 +
 content/doc/1.1.0/gug/using-guacamole.html         |  204 +
 .../1.1.0/gug/writing-you-own-guacamole-app.html   |  436 +
 content/doc/1.1.0/libguac/annotated.html           |  104 +
 content/doc/1.1.0/libguac/audio-fntypes_8h.html    |  234 +
 .../doc/1.1.0/libguac/audio-fntypes_8h_source.html |  100 +
 content/doc/1.1.0/libguac/audio-types_8h.html      |   98 +
 .../doc/1.1.0/libguac/audio-types_8h_source.html   |   93 +
 content/doc/1.1.0/libguac/audio_8h.html            |  388 +
 content/doc/1.1.0/libguac/audio_8h_source.html     |  124 +
 content/doc/1.1.0/libguac/bc_s.png                 |  Bin 0 -> 676 bytes
 content/doc/1.1.0/libguac/bdwn.png                 |  Bin 0 -> 147 bytes
 content/doc/1.1.0/libguac/classes.html             |  107 +
 content/doc/1.1.0/libguac/client-constants_8h.html |  189 +
 .../1.1.0/libguac/client-constants_8h_source.html  |   91 +
 content/doc/1.1.0/libguac/client-fntypes_8h.html   |  186 +
 .../1.1.0/libguac/client-fntypes_8h_source.html    |  101 +
 content/doc/1.1.0/libguac/client-types_8h.html     |  174 +
 .../doc/1.1.0/libguac/client-types_8h_source.html  |  101 +
 content/doc/1.1.0/libguac/client_8h.html           | 1336 +++
 content/doc/1.1.0/libguac/client_8h_source.html    |  156 +
 content/doc/1.1.0/libguac/closed.png               |  Bin 0 -> 132 bytes
 content/doc/1.1.0/libguac/deprecated.html          |   93 +
 .../dir_6bb9fad85c98b48a11165f494b9f53ce.html      |  215 +
 content/doc/1.1.0/libguac/doc.png                  |  Bin 0 -> 746 bytes
 content/doc/1.1.0/libguac/doxygen.css              | 1596 ++++
 content/doc/1.1.0/libguac/doxygen.png              |  Bin 0 -> 3779 bytes
 content/doc/1.1.0/libguac/dynsections.js           |  120 +
 content/doc/1.1.0/libguac/error-types_8h.html      |  205 +
 .../doc/1.1.0/libguac/error-types_8h_source.html   |  116 +
 content/doc/1.1.0/libguac/error_8h.html            |  197 +
 content/doc/1.1.0/libguac/error_8h_source.html     |   94 +
 content/doc/1.1.0/libguac/files.html               |  132 +
 content/doc/1.1.0/libguac/folderclosed.png         |  Bin 0 -> 616 bytes
 content/doc/1.1.0/libguac/folderopen.png           |  Bin 0 -> 597 bytes
 content/doc/1.1.0/libguac/functions.html           |  375 +
 content/doc/1.1.0/libguac/functions_vars.html      |  375 +
 content/doc/1.1.0/libguac/globals.html             |  120 +
 content/doc/1.1.0/libguac/globals_c.html           |  183 +
 content/doc/1.1.0/libguac/globals_defs.html        |  178 +
 content/doc/1.1.0/libguac/globals_e.html           |   93 +
 content/doc/1.1.0/libguac/globals_enum.html        |  115 +
 content/doc/1.1.0/libguac/globals_eval.html        |  261 +
 content/doc/1.1.0/libguac/globals_func.html        |  558 ++
 content/doc/1.1.0/libguac/globals_g.html           |  345 +
 content/doc/1.1.0/libguac/globals_h.html           |   90 +
 content/doc/1.1.0/libguac/globals_l.html           |   93 +
 content/doc/1.1.0/libguac/globals_p.html           |  288 +
 content/doc/1.1.0/libguac/globals_s.html           |  186 +
 content/doc/1.1.0/libguac/globals_t.html           |   99 +
 content/doc/1.1.0/libguac/globals_type.html        |  202 +
 content/doc/1.1.0/libguac/globals_u.html           |  213 +
 content/doc/1.1.0/libguac/globals_vars.html        |   88 +
 content/doc/1.1.0/libguac/hash_8h.html             |  177 +
 content/doc/1.1.0/libguac/hash_8h_source.html      |   93 +
 content/doc/1.1.0/libguac/index.html               |   87 +
 content/doc/1.1.0/libguac/jquery.js                |  115 +
 content/doc/1.1.0/libguac/layer-types_8h.html      |   98 +
 .../doc/1.1.0/libguac/layer-types_8h_source.html   |   92 +
 content/doc/1.1.0/libguac/layer_8h.html            |  107 +
 content/doc/1.1.0/libguac/layer_8h_source.html     |   94 +
 content/doc/1.1.0/libguac/menu.js                  |   50 +
 content/doc/1.1.0/libguac/menudata.js              |  107 +
 content/doc/1.1.0/libguac/nav_f.png                |  Bin 0 -> 153 bytes
 content/doc/1.1.0/libguac/nav_g.png                |  Bin 0 -> 95 bytes
 content/doc/1.1.0/libguac/nav_h.png                |  Bin 0 -> 98 bytes
 content/doc/1.1.0/libguac/object-types_8h.html     |   98 +
 .../doc/1.1.0/libguac/object-types_8h_source.html  |   92 +
 content/doc/1.1.0/libguac/object_8h.html           |  107 +
 content/doc/1.1.0/libguac/object_8h_source.html    |  100 +
 content/doc/1.1.0/libguac/open.png                 |  Bin 0 -> 123 bytes
 content/doc/1.1.0/libguac/pages.html               |   92 +
 content/doc/1.1.0/libguac/parser-constants_8h.html |  116 +
 .../1.1.0/libguac/parser-constants_8h_source.html  |   91 +
 content/doc/1.1.0/libguac/parser-types_8h.html     |  138 +
 .../doc/1.1.0/libguac/parser-types_8h_source.html  |   97 +
 content/doc/1.1.0/libguac/parser_8h.html           |  399 +
 content/doc/1.1.0/libguac/parser_8h_source.html    |  109 +
 content/doc/1.1.0/libguac/plugin-constants_8h.html |  139 +
 .../1.1.0/libguac/plugin-constants_8h_source.html  |   91 +
 content/doc/1.1.0/libguac/plugin_8h.html           |   98 +
 content/doc/1.1.0/libguac/plugin_8h_source.html    |   92 +
 content/doc/1.1.0/libguac/pool-types_8h.html       |   98 +
 .../doc/1.1.0/libguac/pool-types_8h_source.html    |   93 +
 content/doc/1.1.0/libguac/pool_8h.html             |  246 +
 content/doc/1.1.0/libguac/pool_8h_source.html      |  101 +
 .../doc/1.1.0/libguac/protocol-constants_8h.html   |  146 +
 .../libguac/protocol-constants_8h_source.html      |   91 +
 content/doc/1.1.0/libguac/protocol-types_8h.html   |  295 +
 .../1.1.0/libguac/protocol-types_8h_source.html    |  117 +
 content/doc/1.1.0/libguac/protocol_8h.html         | 3178 +++++++
 content/doc/1.1.0/libguac/protocol_8h_source.html  |  162 +
 content/doc/1.1.0/libguac/search/all_0.html        |   40 +
 content/doc/1.1.0/libguac/search/all_0.js          |   14 +
 content/doc/1.1.0/libguac/search/all_1.html        |   40 +
 content/doc/1.1.0/libguac/search/all_1.js          |    6 +
 content/doc/1.1.0/libguac/search/all_10.html       |   40 +
 content/doc/1.1.0/libguac/search/all_10.js         |   19 +
 content/doc/1.1.0/libguac/search/all_11.html       |   40 +
 content/doc/1.1.0/libguac/search/all_11.js         |    6 +
 content/doc/1.1.0/libguac/search/all_12.html       |   40 +
 content/doc/1.1.0/libguac/search/all_12.js         |   10 +
 content/doc/1.1.0/libguac/search/all_13.html       |   40 +
 content/doc/1.1.0/libguac/search/all_13.js         |   10 +
 content/doc/1.1.0/libguac/search/all_14.html       |   40 +
 content/doc/1.1.0/libguac/search/all_14.js         |    4 +
 content/doc/1.1.0/libguac/search/all_2.html        |   40 +
 content/doc/1.1.0/libguac/search/all_2.js          |   13 +
 content/doc/1.1.0/libguac/search/all_3.html        |   40 +
 content/doc/1.1.0/libguac/search/all_3.js          |    5 +
 content/doc/1.1.0/libguac/search/all_4.html        |   40 +
 content/doc/1.1.0/libguac/search/all_4.js          |    7 +
 content/doc/1.1.0/libguac/search/all_5.html        |   40 +
 content/doc/1.1.0/libguac/search/all_5.js          |    7 +
 content/doc/1.1.0/libguac/search/all_6.html        |   40 +
 content/doc/1.1.0/libguac/search/all_6.js          |  291 +
 content/doc/1.1.0/libguac/search/all_7.html        |   40 +
 content/doc/1.1.0/libguac/search/all_7.js          |    4 +
 content/doc/1.1.0/libguac/search/all_8.html        |   40 +
 content/doc/1.1.0/libguac/search/all_8.js          |    6 +
 content/doc/1.1.0/libguac/search/all_9.html        |   40 +
 content/doc/1.1.0/libguac/search/all_9.js          |    4 +
 content/doc/1.1.0/libguac/search/all_a.html        |   40 +
 content/doc/1.1.0/libguac/search/all_a.js          |    4 +
 content/doc/1.1.0/libguac/search/all_b.html        |   40 +
 content/doc/1.1.0/libguac/search/all_b.js          |   12 +
 content/doc/1.1.0/libguac/search/all_c.html        |   40 +
 content/doc/1.1.0/libguac/search/all_c.js          |    6 +
 content/doc/1.1.0/libguac/search/all_d.html        |   40 +
 content/doc/1.1.0/libguac/search/all_d.js          |   10 +
 content/doc/1.1.0/libguac/search/all_e.html        |   40 +
 content/doc/1.1.0/libguac/search/all_e.js          |   16 +
 content/doc/1.1.0/libguac/search/all_f.html        |   40 +
 content/doc/1.1.0/libguac/search/all_f.js          |    5 +
 content/doc/1.1.0/libguac/search/classes_0.html    |   40 +
 content/doc/1.1.0/libguac/search/classes_0.js      |   16 +
 content/doc/1.1.0/libguac/search/close.png         |  Bin 0 -> 273 bytes
 content/doc/1.1.0/libguac/search/defines_0.html    |   40 +
 content/doc/1.1.0/libguac/search/defines_0.js      |   32 +
 content/doc/1.1.0/libguac/search/enums_0.html      |   40 +
 content/doc/1.1.0/libguac/search/enums_0.js        |   13 +
 content/doc/1.1.0/libguac/search/enumvalues_0.html |   40 +
 content/doc/1.1.0/libguac/search/enumvalues_0.js   |   61 +
 content/doc/1.1.0/libguac/search/files_0.html      |   40 +
 content/doc/1.1.0/libguac/search/files_0.js        |    6 +
 content/doc/1.1.0/libguac/search/files_1.html      |   40 +
 content/doc/1.1.0/libguac/search/files_1.js        |    7 +
 content/doc/1.1.0/libguac/search/files_2.html      |   40 +
 content/doc/1.1.0/libguac/search/files_2.js        |    5 +
 content/doc/1.1.0/libguac/search/files_3.html      |   40 +
 content/doc/1.1.0/libguac/search/files_3.js        |    4 +
 content/doc/1.1.0/libguac/search/files_4.html      |   40 +
 content/doc/1.1.0/libguac/search/files_4.js        |    5 +
 content/doc/1.1.0/libguac/search/files_5.html      |   40 +
 content/doc/1.1.0/libguac/search/files_5.js        |    5 +
 content/doc/1.1.0/libguac/search/files_6.html      |   40 +
 content/doc/1.1.0/libguac/search/files_6.js        |   13 +
 content/doc/1.1.0/libguac/search/files_7.html      |   40 +
 content/doc/1.1.0/libguac/search/files_7.js        |   12 +
 content/doc/1.1.0/libguac/search/files_8.html      |   40 +
 content/doc/1.1.0/libguac/search/files_8.js        |    5 +
 content/doc/1.1.0/libguac/search/files_9.html      |   40 +
 content/doc/1.1.0/libguac/search/files_9.js        |    8 +
 content/doc/1.1.0/libguac/search/functions_0.html  |   40 +
 content/doc/1.1.0/libguac/search/functions_0.js    |  147 +
 content/doc/1.1.0/libguac/search/functions_1.html  |   40 +
 content/doc/1.1.0/libguac/search/functions_1.js    |    8 +
 content/doc/1.1.0/libguac/search/mag_sel.png       |  Bin 0 -> 563 bytes
 content/doc/1.1.0/libguac/search/nomatches.html    |   22 +
 content/doc/1.1.0/libguac/search/pages_0.html      |   40 +
 content/doc/1.1.0/libguac/search/pages_0.js        |    4 +
 content/doc/1.1.0/libguac/search/search.css        |  271 +
 content/doc/1.1.0/libguac/search/search.js         |  814 ++
 content/doc/1.1.0/libguac/search/search_l.png      |  Bin 0 -> 604 bytes
 content/doc/1.1.0/libguac/search/search_m.png      |  Bin 0 -> 158 bytes
 content/doc/1.1.0/libguac/search/search_r.png      |  Bin 0 -> 612 bytes
 content/doc/1.1.0/libguac/search/searchdata.js     |   42 +
 content/doc/1.1.0/libguac/search/typedefs_0.html   |   40 +
 content/doc/1.1.0/libguac/search/typedefs_0.js     |   36 +
 content/doc/1.1.0/libguac/search/variables_0.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_0.js    |   11 +
 content/doc/1.1.0/libguac/search/variables_1.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_1.js    |    6 +
 content/doc/1.1.0/libguac/search/variables_10.html |   40 +
 content/doc/1.1.0/libguac/search/variables_10.js   |    4 +
 content/doc/1.1.0/libguac/search/variables_11.html |   40 +
 content/doc/1.1.0/libguac/search/variables_11.js   |    5 +
 content/doc/1.1.0/libguac/search/variables_12.html |   40 +
 content/doc/1.1.0/libguac/search/variables_12.js   |    5 +
 content/doc/1.1.0/libguac/search/variables_13.html |   40 +
 content/doc/1.1.0/libguac/search/variables_13.js   |    4 +
 content/doc/1.1.0/libguac/search/variables_2.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_2.js    |    9 +
 content/doc/1.1.0/libguac/search/variables_3.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_3.js    |    4 +
 content/doc/1.1.0/libguac/search/variables_4.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_4.js    |    5 +
 content/doc/1.1.0/libguac/search/variables_5.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_5.js    |    7 +
 content/doc/1.1.0/libguac/search/variables_6.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_6.js    |    5 +
 content/doc/1.1.0/libguac/search/variables_7.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_7.js    |    6 +
 content/doc/1.1.0/libguac/search/variables_8.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_8.js    |    4 +
 content/doc/1.1.0/libguac/search/variables_9.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_9.js    |    4 +
 content/doc/1.1.0/libguac/search/variables_a.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_a.js    |   10 +
 content/doc/1.1.0/libguac/search/variables_b.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_b.js    |    6 +
 content/doc/1.1.0/libguac/search/variables_c.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_c.js    |    8 +
 content/doc/1.1.0/libguac/search/variables_d.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_d.js    |    6 +
 content/doc/1.1.0/libguac/search/variables_e.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_e.js    |    5 +
 content/doc/1.1.0/libguac/search/variables_f.html  |   40 +
 content/doc/1.1.0/libguac/search/variables_f.js    |   10 +
 content/doc/1.1.0/libguac/socket-constants_8h.html |  112 +
 .../1.1.0/libguac/socket-constants_8h_source.html  |   91 +
 content/doc/1.1.0/libguac/socket-fntypes_8h.html   |  295 +
 .../1.1.0/libguac/socket-fntypes_8h_source.html    |  100 +
 content/doc/1.1.0/libguac/socket-ssl_8h.html       |  155 +
 .../doc/1.1.0/libguac/socket-ssl_8h_source.html    |   98 +
 content/doc/1.1.0/libguac/socket-types_8h.html     |  133 +
 .../doc/1.1.0/libguac/socket-types_8h_source.html  |   95 +
 content/doc/1.1.0/libguac/socket-wsa_8h.html       |  137 +
 .../doc/1.1.0/libguac/socket-wsa_8h_source.html    |   94 +
 content/doc/1.1.0/libguac/socket_8h.html           |  746 ++
 content/doc/1.1.0/libguac/socket_8h_source.html    |  134 +
 content/doc/1.1.0/libguac/splitbar.png             |  Bin 0 -> 314 bytes
 content/doc/1.1.0/libguac/stream-types_8h.html     |   98 +
 .../doc/1.1.0/libguac/stream-types_8h_source.html  |   92 +
 content/doc/1.1.0/libguac/stream_8h.html           |  107 +
 content/doc/1.1.0/libguac/stream_8h_source.html    |  102 +
 content/doc/1.1.0/libguac/string_8h.html           |  275 +
 content/doc/1.1.0/libguac/string_8h_source.html    |   95 +
 .../1.1.0/libguac/structguac__audio__encoder.html  |  125 +
 .../1.1.0/libguac/structguac__audio__stream.html   |  163 +
 content/doc/1.1.0/libguac/structguac__client.html  |  313 +
 content/doc/1.1.0/libguac/structguac__layer.html   |  105 +
 content/doc/1.1.0/libguac/structguac__object.html  |  150 +
 content/doc/1.1.0/libguac/structguac__parser.html  |  117 +
 content/doc/1.1.0/libguac/structguac__pool.html    |  110 +
 .../doc/1.1.0/libguac/structguac__pool__int.html   |  105 +
 content/doc/1.1.0/libguac/structguac__socket.html  |  142 +
 .../libguac/structguac__socket__ssl__data.html     |  113 +
 content/doc/1.1.0/libguac/structguac__stream.html  |  170 +
 content/doc/1.1.0/libguac/structguac__user.html    |  540 ++
 .../doc/1.1.0/libguac/structguac__user__info.html  |  242 +
 content/doc/1.1.0/libguac/sync_off.png             |  Bin 0 -> 853 bytes
 content/doc/1.1.0/libguac/sync_on.png              |  Bin 0 -> 845 bytes
 content/doc/1.1.0/libguac/tab_a.png                |  Bin 0 -> 142 bytes
 content/doc/1.1.0/libguac/tab_b.png                |  Bin 0 -> 169 bytes
 content/doc/1.1.0/libguac/tab_h.png                |  Bin 0 -> 177 bytes
 content/doc/1.1.0/libguac/tab_s.png                |  Bin 0 -> 184 bytes
 content/doc/1.1.0/libguac/tabs.css                 |    1 +
 content/doc/1.1.0/libguac/timestamp-types_8h.html  |  108 +
 .../1.1.0/libguac/timestamp-types_8h_source.html   |   92 +
 content/doc/1.1.0/libguac/timestamp_8h.html        |  158 +
 content/doc/1.1.0/libguac/timestamp_8h_source.html |   95 +
 content/doc/1.1.0/libguac/unicode_8h.html          |  263 +
 content/doc/1.1.0/libguac/unicode_8h_source.html   |   95 +
 content/doc/1.1.0/libguac/user-constants_8h.html   |  149 +
 .../1.1.0/libguac/user-constants_8h_source.html    |   91 +
 content/doc/1.1.0/libguac/user-fntypes_8h.html     |  612 ++
 .../doc/1.1.0/libguac/user-fntypes_8h_source.html  |  118 +
 content/doc/1.1.0/libguac/user-types_8h.html       |   98 +
 .../doc/1.1.0/libguac/user-types_8h_source.html    |   93 +
 content/doc/1.1.0/libguac/user_8h.html             | 1187 +++
 content/doc/1.1.0/libguac/user_8h_source.html      |  180 +
 content/releases/1.1.0/index.html                  | 1293 +++
 882 files changed, 255118 insertions(+)

diff --git a/content/doc/1.1.0/guacamole-common-js/ArrayBufferReader.js.html b/content/doc/1.1.0/guacamole-common-js/ArrayBufferReader.js.html
new file mode 100644
index 0000000..ffa83de
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/ArrayBufferReader.js.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: ArrayBufferReader.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: ArrayBufferReader.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * A reader which automatically handles the given input stream, returning
+ * strictly received packets as array buffers. Note that this object will
+ * overwrite any installed event handlers on the given Guacamole.InputStream.
+ * 
+ * @constructor
+ * @param {Guacamole.InputStream} stream The stream that data will be read
+ *                                       from.
+ */
+Guacamole.ArrayBufferReader = function(stream) {
+
+    /**
+     * Reference to this Guacamole.InputStream.
+     * @private
+     */
+    var guac_reader = this;
+
+    // Receive blobs as array buffers
+    stream.onblob = function(data) {
+
+        // Convert to ArrayBuffer
+        var binary = window.atob(data);
+        var arrayBuffer = new ArrayBuffer(binary.length);
+        var bufferView = new Uint8Array(arrayBuffer);
+
+        for (var i=0; i&lt;binary.length; i++)
+            bufferView[i] = binary.charCodeAt(i);
+
+        // Call handler, if present
+        if (guac_reader.ondata)
+            guac_reader.ondata(arrayBuffer);
+
+    };
+
+    // Simply call onend when end received
+    stream.onend = function() {
+        if (guac_reader.onend)
+            guac_reader.onend();
+    };
+
+    /**
+     * Fired once for every blob of data received.
+     * 
+     * @event
+     * @param {ArrayBuffer} buffer The data packet received.
+     */
+    this.ondata = null;
+
+    /**
+     * Fired once this stream is finished and no further data will be written.
+     * @event
+     */
+    this.onend = null;
+
+};</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/ArrayBufferWriter.js.html b/content/doc/1.1.0/guacamole-common-js/ArrayBufferWriter.js.html
new file mode 100644
index 0000000..9849d69
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/ArrayBufferWriter.js.html
@@ -0,0 +1,184 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: ArrayBufferWriter.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: ArrayBufferWriter.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * A writer which automatically writes to the given output stream with arbitrary
+ * binary data, supplied as ArrayBuffers.
+ * 
+ * @constructor
+ * @param {Guacamole.OutputStream} stream The stream that data will be written
+ *                                        to.
+ */
+Guacamole.ArrayBufferWriter = function(stream) {
+
+    /**
+     * Reference to this Guacamole.StringWriter.
+     * @private
+     */
+    var guac_writer = this;
+
+    // Simply call onack for acknowledgements
+    stream.onack = function(status) {
+        if (guac_writer.onack)
+            guac_writer.onack(status);
+    };
+
+    /**
+     * Encodes the given data as base64, sending it as a blob. The data must
+     * be small enough to fit into a single blob instruction.
+     * 
+     * @private
+     * @param {Uint8Array} bytes The data to send.
+     */
+    function __send_blob(bytes) {
+
+        var binary = "";
+
+        // Produce binary string from bytes in buffer
+        for (var i=0; i&lt;bytes.byteLength; i++)
+            binary += String.fromCharCode(bytes[i]);
+
+        // Send as base64
+        stream.sendBlob(window.btoa(binary));
+
+    }
+
+    /**
+     * The maximum length of any blob sent by this Guacamole.ArrayBufferWriter,
+     * in bytes. Data sent via
+     * [sendData()]{@link Guacamole.ArrayBufferWriter#sendData} which exceeds
+     * this length will be split into multiple blobs. As the Guacamole protocol
+     * limits the maximum size of any instruction or instruction element to
+     * 8192 bytes, and the contents of blobs will be base64-encoded, this value
+     * should only be increased with extreme caution.
+     *
+     * @type {Number}
+     * @default {@link Guacamole.ArrayBufferWriter.DEFAULT_BLOB_LENGTH}
+     */
+    this.blobLength = Guacamole.ArrayBufferWriter.DEFAULT_BLOB_LENGTH;
+
+    /**
+     * Sends the given data.
+     * 
+     * @param {ArrayBuffer|TypedArray} data The data to send.
+     */
+    this.sendData = function(data) {
+
+        var bytes = new Uint8Array(data);
+
+        // If small enough to fit into single instruction, send as-is
+        if (bytes.length &lt;= guac_writer.blobLength)
+            __send_blob(bytes);
+
+        // Otherwise, send as multiple instructions
+        else {
+            for (var offset=0; offset&lt;bytes.length; offset += guac_writer.blobLength)
+                __send_blob(bytes.subarray(offset, offset + guac_writer.blobLength));
+        }
+
+    };
+
+    /**
+     * Signals that no further text will be sent, effectively closing the
+     * stream.
+     */
+    this.sendEnd = function() {
+        stream.sendEnd();
+    };
+
+    /**
+     * Fired for received data, if acknowledged by the server.
+     * @event
+     * @param {Guacamole.Status} status The status of the operation.
+     */
+    this.onack = null;
+
+};
+
+/**
+ * The default maximum blob length for new Guacamole.ArrayBufferWriter
+ * instances.
+ *
+ * @constant
+ * @type {Number}
+ */
+Guacamole.ArrayBufferWriter.DEFAULT_BLOB_LENGTH = 6048;
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/AudioContextFactory.js.html b/content/doc/1.1.0/guacamole-common-js/AudioContextFactory.js.html
new file mode 100644
index 0000000..9305884
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/AudioContextFactory.js.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: AudioContextFactory.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: AudioContextFactory.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * Maintains a singleton instance of the Web Audio API AudioContext class,
+ * instantiating the AudioContext only in response to the first call to
+ * getAudioContext(), and only if no existing AudioContext instance has been
+ * provided via the singleton property. Subsequent calls to getAudioContext()
+ * will return the same instance.
+ *
+ * @namespace
+ */
+Guacamole.AudioContextFactory = {
+
+    /**
+     * A singleton instance of a Web Audio API AudioContext object, or null if
+     * no instance has yes been created. This property may be manually set if
+     * you wish to supply your own AudioContext instance, but care must be
+     * taken to do so as early as possible. Assignments to this property will
+     * not retroactively affect the value returned by previous calls to
+     * getAudioContext().
+     *
+     * @type {AudioContext}
+     */
+    'singleton' : null,
+
+    /**
+     * Returns a singleton instance of a Web Audio API AudioContext object.
+     *
+     * @return {AudioContext}
+     *     A singleton instance of a Web Audio API AudioContext object, or null
+     *     if the Web Audio API is not supported.
+     */
+    'getAudioContext' : function getAudioContext() {
+
+        // Fallback to Webkit-specific AudioContext implementation
+        var AudioContext = window.AudioContext || window.webkitAudioContext;
+
+        // Get new AudioContext instance if Web Audio API is supported
+        if (AudioContext) {
+            try {
+
+                // Create new instance if none yet exists
+                if (!Guacamole.AudioContextFactory.singleton)
+                    Guacamole.AudioContextFactory.singleton = new AudioContext();
+
+                // Return singleton instance
+                return Guacamole.AudioContextFactory.singleton;
+
+            }
+            catch (e) {
+                // Do not use Web Audio API if not allowed by browser
+            }
+        }
+
+        // Web Audio API not supported
+        return null;
+
+    }
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/AudioPlayer.js.html b/content/doc/1.1.0/guacamole-common-js/AudioPlayer.js.html
new file mode 100644
index 0000000..72f2f81
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/AudioPlayer.js.html
@@ -0,0 +1,566 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: AudioPlayer.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: AudioPlayer.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * Abstract audio player which accepts, queues and plays back arbitrary audio
+ * data. It is up to implementations of this class to provide some means of
+ * handling a provided Guacamole.InputStream. Data received along the provided
+ * stream is to be played back immediately.
+ *
+ * @constructor
+ */
+Guacamole.AudioPlayer = function AudioPlayer() {
+
+    /**
+     * Notifies this Guacamole.AudioPlayer that all audio up to the current
+     * point in time has been given via the underlying stream, and that any
+     * difference in time between queued audio data and the current time can be
+     * considered latency.
+     */
+    this.sync = function sync() {
+        // Default implementation - do nothing
+    };
+
+};
+
+/**
+ * Determines whether the given mimetype is supported by any built-in
+ * implementation of Guacamole.AudioPlayer, and thus will be properly handled
+ * by Guacamole.AudioPlayer.getInstance().
+ *
+ * @param {String} mimetype
+ *     The mimetype to check.
+ *
+ * @returns {Boolean}
+ *     true if the given mimetype is supported by any built-in
+ *     Guacamole.AudioPlayer, false otherwise.
+ */
+Guacamole.AudioPlayer.isSupportedType = function isSupportedType(mimetype) {
+
+    return Guacamole.RawAudioPlayer.isSupportedType(mimetype);
+
+};
+
+/**
+ * Returns a list of all mimetypes supported by any built-in
+ * Guacamole.AudioPlayer, in rough order of priority. Beware that only the core
+ * mimetypes themselves will be listed. Any mimetype parameters, even required
+ * ones, will not be included in the list. For example, "audio/L8" is a
+ * supported raw audio mimetype that is supported, but it is invalid without
+ * additional parameters. Something like "audio/L8;rate=44100" would be valid,
+ * however (see https://tools.ietf.org/html/rfc4856).
+ *
+ * @returns {String[]}
+ *     A list of all mimetypes supported by any built-in Guacamole.AudioPlayer,
+ *     excluding any parameters.
+ */
+Guacamole.AudioPlayer.getSupportedTypes = function getSupportedTypes() {
+
+    return Guacamole.RawAudioPlayer.getSupportedTypes();
+
+};
+
+/**
+ * Returns an instance of Guacamole.AudioPlayer providing support for the given
+ * audio format. If support for the given audio format is not available, null
+ * is returned.
+ *
+ * @param {Guacamole.InputStream} stream
+ *     The Guacamole.InputStream to read audio data from.
+ *
+ * @param {String} mimetype
+ *     The mimetype of the audio data in the provided stream.
+ *
+ * @return {Guacamole.AudioPlayer}
+ *     A Guacamole.AudioPlayer instance supporting the given mimetype and
+ *     reading from the given stream, or null if support for the given mimetype
+ *     is absent.
+ */
+Guacamole.AudioPlayer.getInstance = function getInstance(stream, mimetype) {
+
+    // Use raw audio player if possible
+    if (Guacamole.RawAudioPlayer.isSupportedType(mimetype))
+        return new Guacamole.RawAudioPlayer(stream, mimetype);
+
+    // No support for given mimetype
+    return null;
+
+};
+
+/**
+ * Implementation of Guacamole.AudioPlayer providing support for raw PCM format
+ * audio. This player relies only on the Web Audio API and does not require any
+ * browser-level support for its audio formats.
+ *
+ * @constructor
+ * @augments Guacamole.AudioPlayer
+ * @param {Guacamole.InputStream} stream
+ *     The Guacamole.InputStream to read audio data from.
+ *
+ * @param {String} mimetype
+ *     The mimetype of the audio data in the provided stream, which must be a
+ *     "audio/L8" or "audio/L16" mimetype with necessary parameters, such as:
+ *     "audio/L16;rate=44100,channels=2".
+ */
+Guacamole.RawAudioPlayer = function RawAudioPlayer(stream, mimetype) {
+
+    /**
+     * The format of audio this player will decode.
+     *
+     * @private
+     * @type {Guacamole.RawAudioFormat}
+     */
+    var format = Guacamole.RawAudioFormat.parse(mimetype);
+
+    /**
+     * An instance of a Web Audio API AudioContext object, or null if the
+     * Web Audio API is not supported.
+     *
+     * @private
+     * @type {AudioContext}
+     */
+    var context = Guacamole.AudioContextFactory.getAudioContext();
+
+    /**
+     * The earliest possible time that the next packet could play without
+     * overlapping an already-playing packet, in seconds. Note that while this
+     * value is in seconds, it is not an integer value and has microsecond
+     * resolution.
+     *
+     * @private
+     * @type {Number}
+     */
+    var nextPacketTime = context.currentTime;
+
+    /**
+     * Guacamole.ArrayBufferReader wrapped around the audio input stream
+     * provided with this Guacamole.RawAudioPlayer was created.
+     *
+     * @private
+     * @type {Guacamole.ArrayBufferReader}
+     */
+    var reader = new Guacamole.ArrayBufferReader(stream);
+
+    /**
+     * The minimum size of an audio packet split by splitAudioPacket(), in
+     * seconds. Audio packets smaller than this will not be split, nor will the
+     * split result of a larger packet ever be smaller in size than this
+     * minimum.
+     *
+     * @private
+     * @constant
+     * @type {Number}
+     */
+    var MIN_SPLIT_SIZE = 0.02;
+
+    /**
+     * The maximum amount of latency to allow between the buffered data stream
+     * and the playback position, in seconds. Initially, this is set to
+     * roughly one third of a second.
+     *
+     * @private
+     * @type {Number}
+     */
+    var maxLatency = 0.3;
+
+    /**
+     * The type of typed array that will be used to represent each audio packet
+     * internally. This will be either Int8Array or Int16Array, depending on
+     * whether the raw audio format is 8-bit or 16-bit.
+     *
+     * @private
+     * @constructor
+     */
+    var SampleArray = (format.bytesPerSample === 1) ? window.Int8Array : window.Int16Array;
+
+    /**
+     * The maximum absolute value of any sample within a raw audio packet
+     * received by this audio player. This depends only on the size of each
+     * sample, and will be 128 for 8-bit audio and 32768 for 16-bit audio.
+     *
+     * @private
+     * @type {Number}
+     */
+    var maxSampleValue = (format.bytesPerSample === 1) ? 128 : 32768;
+
+    /**
+     * The queue of all pending audio packets, as an array of sample arrays.
+     * Audio packets which are pending playback will be added to this queue for
+     * further manipulation prior to scheduling via the Web Audio API. Once an
+     * audio packet leaves this queue and is scheduled via the Web Audio API,
+     * no further modifications can be made to that packet.
+     *
+     * @private
+     * @type {SampleArray[]}
+     */
+    var packetQueue = [];
+
+    /**
+     * Given an array of audio packets, returns a single audio packet
+     * containing the concatenation of those packets.
+     *
+     * @private
+     * @param {SampleArray[]} packets
+     *     The array of audio packets to concatenate.
+     *
+     * @returns {SampleArray}
+     *     A single audio packet containing the concatenation of all given
+     *     audio packets. If no packets are provided, this will be undefined.
+     */
+    var joinAudioPackets = function joinAudioPackets(packets) {
+
+        // Do not bother joining if one or fewer packets are in the queue
+        if (packets.length &lt;= 1)
+            return packets[0];
+
+        // Determine total sample length of the entire queue
+        var totalLength = 0;
+        packets.forEach(function addPacketLengths(packet) {
+            totalLength += packet.length;
+        });
+
+        // Append each packet within queue
+        var offset = 0;
+        var joined = new SampleArray(totalLength);
+        packets.forEach(function appendPacket(packet) {
+            joined.set(packet, offset);
+            offset += packet.length;
+        });
+
+        return joined;
+
+    };
+
+    /**
+     * Given a single packet of audio data, splits off an arbitrary length of
+     * audio data from the beginning of that packet, returning the split result
+     * as an array of two packets. The split location is determined through an
+     * algorithm intended to minimize the liklihood of audible clicking between
+     * packets. If no such split location is possible, an array containing only
+     * the originally-provided audio packet is returned.
+     *
+     * @private
+     * @param {SampleArray} data
+     *     The audio packet to split.
+     *
+     * @returns {SampleArray[]}
+     *     An array of audio packets containing the result of splitting the
+     *     provided audio packet. If splitting is possible, this array will
+     *     contain two packets. If splitting is not possible, this array will
+     *     contain only the originally-provided packet.
+     */
+    var splitAudioPacket = function splitAudioPacket(data) {
+
+        var minValue = Number.MAX_VALUE;
+        var optimalSplitLength = data.length;
+
+        // Calculate number of whole samples in the provided audio packet AND
+        // in the minimum possible split packet
+        var samples = Math.floor(data.length / format.channels);
+        var minSplitSamples = Math.floor(format.rate * MIN_SPLIT_SIZE);
+
+        // Calculate the beginning of the "end" of the audio packet
+        var start = Math.max(
+            format.channels * minSplitSamples,
+            format.channels * (samples - minSplitSamples)
+        );
+
+        // For all samples at the end of the given packet, find a point where
+        // the perceptible volume across all channels is lowest (and thus is
+        // the optimal point to split)
+        for (var offset = start; offset &lt; data.length; offset += format.channels) {
+
+            // Calculate the sum of all values across all channels (the result
+            // will be proportional to the average volume of a sample)
+            var totalValue = 0;
+            for (var channel = 0; channel &lt; format.channels; channel++) {
+                totalValue += Math.abs(data[offset + channel]);
+            }
+
+            // If this is the smallest average value thus far, set the split
+            // length such that the first packet ends with the current sample
+            if (totalValue &lt;= minValue) {
+                optimalSplitLength = offset + format.channels;
+                minValue = totalValue;
+            }
+
+        }
+
+        // If packet is not split, return the supplied packet untouched
+        if (optimalSplitLength === data.length)
+            return [data];
+
+        // Otherwise, split the packet into two new packets according to the
+        // calculated optimal split length
+        return [
+            new SampleArray(data.buffer.slice(0, optimalSplitLength * format.bytesPerSample)),
+            new SampleArray(data.buffer.slice(optimalSplitLength * format.bytesPerSample))
+        ];
+
+    };
+
+    /**
+     * Pushes the given packet of audio data onto the playback queue. Unlike
+     * other private functions within Guacamole.RawAudioPlayer, the type of the
+     * ArrayBuffer packet of audio data here need not be specific to the type
+     * of audio (as with SampleArray). The ArrayBuffer type provided by a
+     * Guacamole.ArrayBufferReader, for example, is sufficient. Any necessary
+     * conversions will be performed automatically internally.
+     *
+     * @private
+     * @param {ArrayBuffer} data
+     *     A raw packet of audio data that should be pushed onto the audio
+     *     playback queue.
+     */
+    var pushAudioPacket = function pushAudioPacket(data) {
+        packetQueue.push(new SampleArray(data));
+    };
+
+    /**
+     * Shifts off and returns a packet of audio data from the beginning of the
+     * playback queue. The length of this audio packet is determined
+     * dynamically according to the click-reduction algorithm implemented by
+     * splitAudioPacket().
+     *
+     * @private
+     * @returns {SampleArray}
+     *     A packet of audio data pulled from the beginning of the playback
+     *     queue.
+     */
+    var shiftAudioPacket = function shiftAudioPacket() {
+
+        // Flatten data in packet queue
+        var data = joinAudioPackets(packetQueue);
+        if (!data)
+            return null;
+
+        // Pull an appropriate amount of data from the front of the queue
+        packetQueue = splitAudioPacket(data);
+        data = packetQueue.shift();
+
+        return data;
+
+    };
+
+    /**
+     * Converts the given audio packet into an AudioBuffer, ready for playback
+     * by the Web Audio API. Unlike the raw audio packets received by this
+     * audio player, AudioBuffers require floating point samples and are split
+     * into isolated planes of channel-specific data.
+     *
+     * @private
+     * @param {SampleArray} data
+     *     The raw audio packet that should be converted into a Web Audio API
+     *     AudioBuffer.
+     *
+     * @returns {AudioBuffer}
+     *     A new Web Audio API AudioBuffer containing the provided audio data,
+     *     converted to the format used by the Web Audio API.
+     */
+    var toAudioBuffer = function toAudioBuffer(data) {
+
+        // Calculate total number of samples
+        var samples = data.length / format.channels;
+
+        // Determine exactly when packet CAN play
+        var packetTime = context.currentTime;
+        if (nextPacketTime &lt; packetTime)
+            nextPacketTime = packetTime;
+
+        // Get audio buffer for specified format
+        var audioBuffer = context.createBuffer(format.channels, samples, format.rate);
+
+        // Convert each channel
+        for (var channel = 0; channel &lt; format.channels; channel++) {
+
+            var audioData = audioBuffer.getChannelData(channel);
+
+            // Fill audio buffer with data for channel
+            var offset = channel;
+            for (var i = 0; i &lt; samples; i++) {
+                audioData[i] = data[offset] / maxSampleValue;
+                offset += format.channels;
+            }
+
+        }
+
+        return audioBuffer;
+
+    };
+
+    // Defer playback of received audio packets slightly
+    reader.ondata = function playReceivedAudio(data) {
+
+        // Push received samples onto queue
+        pushAudioPacket(new SampleArray(data));
+
+        // Shift off an arbitrary packet of audio data from the queue (this may
+        // be different in size from the packet just pushed)
+        var packet = shiftAudioPacket();
+        if (!packet)
+            return;
+
+        // Determine exactly when packet CAN play
+        var packetTime = context.currentTime;
+        if (nextPacketTime &lt; packetTime)
+            nextPacketTime = packetTime;
+
+        // Set up buffer source
+        var source = context.createBufferSource();
+        source.connect(context.destination);
+
+        // Use noteOn() instead of start() if necessary
+        if (!source.start)
+            source.start = source.noteOn;
+
+        // Schedule packet
+        source.buffer = toAudioBuffer(packet);
+        source.start(nextPacketTime);
+
+        // Update timeline by duration of scheduled packet
+        nextPacketTime += packet.length / format.channels / format.rate;
+
+    };
+
+    /** @override */
+    this.sync = function sync() {
+
+        // Calculate elapsed time since last sync
+        var now = context.currentTime;
+
+        // Reschedule future playback time such that playback latency is
+        // bounded within a reasonable latency threshold
+        nextPacketTime = Math.min(nextPacketTime, now + maxLatency);
+
+    };
+
+};
+
+Guacamole.RawAudioPlayer.prototype = new Guacamole.AudioPlayer();
+
+/**
+ * Determines whether the given mimetype is supported by
+ * Guacamole.RawAudioPlayer.
+ *
+ * @param {String} mimetype
+ *     The mimetype to check.
+ *
+ * @returns {Boolean}
+ *     true if the given mimetype is supported by Guacamole.RawAudioPlayer,
+ *     false otherwise.
+ */
+Guacamole.RawAudioPlayer.isSupportedType = function isSupportedType(mimetype) {
+
+    // No supported types if no Web Audio API
+    if (!Guacamole.AudioContextFactory.getAudioContext())
+        return false;
+
+    return Guacamole.RawAudioFormat.parse(mimetype) !== null;
+
+};
+
+/**
+ * Returns a list of all mimetypes supported by Guacamole.RawAudioPlayer. Only
+ * the core mimetypes themselves will be listed. Any mimetype parameters, even
+ * required ones, will not be included in the list. For example, "audio/L8" is
+ * a raw audio mimetype that may be supported, but it is invalid without
+ * additional parameters. Something like "audio/L8;rate=44100" would be valid,
+ * however (see https://tools.ietf.org/html/rfc4856).
+ *
+ * @returns {String[]}
+ *     A list of all mimetypes supported by Guacamole.RawAudioPlayer, excluding
+ *     any parameters. If the necessary JavaScript APIs for playing raw audio
+ *     are absent, this list will be empty.
+ */
+Guacamole.RawAudioPlayer.getSupportedTypes = function getSupportedTypes() {
+
+    // No supported types if no Web Audio API
+    if (!Guacamole.AudioContextFactory.getAudioContext())
+        return [];
+
+    // We support 8-bit and 16-bit raw PCM
+    return [
+        'audio/L8',
+        'audio/L16'
+    ];
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/AudioRecorder.js.html b/content/doc/1.1.0/guacamole-common-js/AudioRecorder.js.html
new file mode 100644
index 0000000..a118160
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/AudioRecorder.js.html
@@ -0,0 +1,632 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: AudioRecorder.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: AudioRecorder.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * Abstract audio recorder which streams arbitrary audio data to an underlying
+ * Guacamole.OutputStream. It is up to implementations of this class to provide
+ * some means of handling this Guacamole.OutputStream. Data produced by the
+ * recorder is to be sent along the provided stream immediately.
+ *
+ * @constructor
+ */
+Guacamole.AudioRecorder = function AudioRecorder() {
+
+    /**
+     * Callback which is invoked when the audio recording process has stopped
+     * and the underlying Guacamole stream has been closed normally. Audio will
+     * only resume recording if a new Guacamole.AudioRecorder is started. This
+     * Guacamole.AudioRecorder instance MAY NOT be reused.
+     *
+     * @event
+     */
+    this.onclose = null;
+
+    /**
+     * Callback which is invoked when the audio recording process cannot
+     * continue due to an error, if it has started at all. The underlying
+     * Guacamole stream is automatically closed. Future attempts to record
+     * audio should not be made, and this Guacamole.AudioRecorder instance
+     * MAY NOT be reused.
+     *
+     * @event
+     */
+    this.onerror = null;
+
+};
+
+/**
+ * Determines whether the given mimetype is supported by any built-in
+ * implementation of Guacamole.AudioRecorder, and thus will be properly handled
+ * by Guacamole.AudioRecorder.getInstance().
+ *
+ * @param {String} mimetype
+ *     The mimetype to check.
+ *
+ * @returns {Boolean}
+ *     true if the given mimetype is supported by any built-in
+ *     Guacamole.AudioRecorder, false otherwise.
+ */
+Guacamole.AudioRecorder.isSupportedType = function isSupportedType(mimetype) {
+
+    return Guacamole.RawAudioRecorder.isSupportedType(mimetype);
+
+};
+
+/**
+ * Returns a list of all mimetypes supported by any built-in
+ * Guacamole.AudioRecorder, in rough order of priority. Beware that only the
+ * core mimetypes themselves will be listed. Any mimetype parameters, even
+ * required ones, will not be included in the list. For example, "audio/L8" is
+ * a supported raw audio mimetype that is supported, but it is invalid without
+ * additional parameters. Something like "audio/L8;rate=44100" would be valid,
+ * however (see https://tools.ietf.org/html/rfc4856).
+ *
+ * @returns {String[]}
+ *     A list of all mimetypes supported by any built-in
+ *     Guacamole.AudioRecorder, excluding any parameters.
+ */
+Guacamole.AudioRecorder.getSupportedTypes = function getSupportedTypes() {
+
+    return Guacamole.RawAudioRecorder.getSupportedTypes();
+
+};
+
+/**
+ * Returns an instance of Guacamole.AudioRecorder providing support for the
+ * given audio format. If support for the given audio format is not available,
+ * null is returned.
+ *
+ * @param {Guacamole.OutputStream} stream
+ *     The Guacamole.OutputStream to send audio data through.
+ *
+ * @param {String} mimetype
+ *     The mimetype of the audio data to be sent along the provided stream.
+ *
+ * @return {Guacamole.AudioRecorder}
+ *     A Guacamole.AudioRecorder instance supporting the given mimetype and
+ *     writing to the given stream, or null if support for the given mimetype
+ *     is absent.
+ */
+Guacamole.AudioRecorder.getInstance = function getInstance(stream, mimetype) {
+
+    // Use raw audio recorder if possible
+    if (Guacamole.RawAudioRecorder.isSupportedType(mimetype))
+        return new Guacamole.RawAudioRecorder(stream, mimetype);
+
+    // No support for given mimetype
+    return null;
+
+};
+
+/**
+ * Implementation of Guacamole.AudioRecorder providing support for raw PCM
+ * format audio. This recorder relies only on the Web Audio API and does not
+ * require any browser-level support for its audio formats.
+ *
+ * @constructor
+ * @augments Guacamole.AudioRecorder
+ * @param {Guacamole.OutputStream} stream
+ *     The Guacamole.OutputStream to write audio data to.
+ *
+ * @param {String} mimetype
+ *     The mimetype of the audio data to send along the provided stream, which
+ *     must be a "audio/L8" or "audio/L16" mimetype with necessary parameters,
+ *     such as: "audio/L16;rate=44100,channels=2".
+ */
+Guacamole.RawAudioRecorder = function RawAudioRecorder(stream, mimetype) {
+
+    /**
+     * Reference to this RawAudioRecorder.
+     *
+     * @private
+     * @type {Guacamole.RawAudioRecorder}
+     */
+    var recorder = this;
+
+    /**
+     * The size of audio buffer to request from the Web Audio API when
+     * recording or processing audio, in sample-frames. This must be a power of
+     * two between 256 and 16384 inclusive, as required by
+     * AudioContext.createScriptProcessor().
+     *
+     * @private
+     * @constant
+     * @type {Number}
+     */
+    var BUFFER_SIZE = 2048;
+
+    /**
+     * The window size to use when applying Lanczos interpolation, commonly
+     * denoted by the variable "a".
+     * See: https://en.wikipedia.org/wiki/Lanczos_resampling
+     *
+     * @private
+     * @contant
+     * @type Number
+     */
+    var LANCZOS_WINDOW_SIZE = 3;
+
+    /**
+     * The format of audio this recorder will encode.
+     *
+     * @private
+     * @type {Guacamole.RawAudioFormat}
+     */
+    var format = Guacamole.RawAudioFormat.parse(mimetype);
+
+    /**
+     * An instance of a Web Audio API AudioContext object, or null if the
+     * Web Audio API is not supported.
+     *
+     * @private
+     * @type {AudioContext}
+     */
+    var context = Guacamole.AudioContextFactory.getAudioContext();
+
+    // Some browsers do not implement navigator.mediaDevices - this
+    // shims in this functionality to ensure code compatibility.
+    if (!navigator.mediaDevices)
+        navigator.mediaDevices = {};
+
+    // Browsers that either do not implement navigator.mediaDevices
+    // at all or do not implement it completely need the getUserMedia
+    // method defined.  This shims in this function by detecting
+    // one of the supported legacy methods.
+    if (!navigator.mediaDevices.getUserMedia)
+        navigator.mediaDevices.getUserMedia = (navigator.getUserMedia
+                || navigator.webkitGetUserMedia
+                || navigator.mozGetUserMedia
+                || navigator.msGetUserMedia).bind(navigator);
+
+    /**
+     * Guacamole.ArrayBufferWriter wrapped around the audio output stream
+     * provided when this Guacamole.RawAudioRecorder was created.
+     *
+     * @private
+     * @type {Guacamole.ArrayBufferWriter}
+     */
+    var writer = new Guacamole.ArrayBufferWriter(stream);
+
+    /**
+     * The type of typed array that will be used to represent each audio packet
+     * internally. This will be either Int8Array or Int16Array, depending on
+     * whether the raw audio format is 8-bit or 16-bit.
+     *
+     * @private
+     * @constructor
+     */
+    var SampleArray = (format.bytesPerSample === 1) ? window.Int8Array : window.Int16Array;
+
+    /**
+     * The maximum absolute value of any sample within a raw audio packet sent
+     * by this audio recorder. This depends only on the size of each sample,
+     * and will be 128 for 8-bit audio and 32768 for 16-bit audio.
+     *
+     * @private
+     * @type {Number}
+     */
+    var maxSampleValue = (format.bytesPerSample === 1) ? 128 : 32768;
+
+    /**
+     * The total number of audio samples read from the local audio input device
+     * over the life of this audio recorder.
+     *
+     * @private
+     * @type {Number}
+     */
+    var readSamples = 0;
+
+    /**
+     * The total number of audio samples written to the underlying Guacamole
+     * connection over the life of this audio recorder.
+     *
+     * @private
+     * @type {Number}
+     */
+    var writtenSamples = 0;
+
+    /**
+     * The audio stream provided by the browser, if allowed. If no stream has
+     * yet been received, this will be null.
+     *
+     * @type MediaStream
+     */
+    var mediaStream = null;
+
+    /**
+     * The source node providing access to the local audio input device.
+     *
+     * @private
+     * @type {MediaStreamAudioSourceNode}
+     */
+    var source = null;
+
+    /**
+     * The script processing node which receives audio input from the media
+     * stream source node as individual audio buffers.
+     *
+     * @private
+     * @type {ScriptProcessorNode}
+     */
+    var processor = null;
+
+    /**
+     * The normalized sinc function. The normalized sinc function is defined as
+     * 1 for x=0 and sin(PI * x) / (PI * x) for all other values of x.
+     *
+     * See: https://en.wikipedia.org/wiki/Sinc_function
+     *
+     * @private
+     * @param {Number} x
+     *     The point at which the normalized sinc function should be computed.
+     *
+     * @returns {Number}
+     *     The value of the normalized sinc function at x.
+     */
+    var sinc = function sinc(x) {
+
+        // The value of sinc(0) is defined as 1
+        if (x === 0)
+            return 1;
+
+        // Otherwise, normlized sinc(x) is sin(PI * x) / (PI * x)
+        var piX = Math.PI * x;
+        return Math.sin(piX) / piX;
+
+    };
+
+    /**
+     * Calculates the value of the Lanczos kernal at point x for a given window
+     * size. See: https://en.wikipedia.org/wiki/Lanczos_resampling
+     *
+     * @private
+     * @param {Number} x
+     *     The point at which the value of the Lanczos kernel should be
+     *     computed.
+     *
+     * @param {Number} a
+     *     The window size to use for the Lanczos kernel.
+     *
+     * @returns {Number}
+     *     The value of the Lanczos kernel at the given point for the given
+     *     window size.
+     */
+    var lanczos = function lanczos(x, a) {
+
+        // Lanczos is sinc(x) * sinc(x / a) for -a &lt; x &lt; a ...
+        if (-a &lt; x &amp;&amp; x &lt; a)
+            return sinc(x) * sinc(x / a);
+
+        // ... and 0 otherwise
+        return 0;
+
+    };
+
+    /**
+     * Determines the value of the waveform represented by the audio data at
+     * the given location. If the value cannot be determined exactly as it does
+     * not correspond to an exact sample within the audio data, the value will
+     * be derived through interpolating nearby samples.
+     *
+     * @private
+     * @param {Float32Array} audioData
+     *     An array of audio data, as returned by AudioBuffer.getChannelData().
+     *
+     * @param {Number} t
+     *     The relative location within the waveform from which the value
+     *     should be retrieved, represented as a floating point number between
+     *     0 and 1 inclusive, where 0 represents the earliest point in time and
+     *     1 represents the latest.
+     *
+     * @returns {Number}
+     *     The value of the waveform at the given location.
+     */
+    var interpolateSample = function getValueAt(audioData, t) {
+
+        // Convert [0, 1] range to [0, audioData.length - 1]
+        var index = (audioData.length - 1) * t;
+
+        // Determine the start and end points for the summation used by the
+        // Lanczos interpolation algorithm (see: https://en.wikipedia.org/wiki/Lanczos_resampling)
+        var start = Math.floor(index) - LANCZOS_WINDOW_SIZE + 1;
+        var end = Math.floor(index) + LANCZOS_WINDOW_SIZE;
+
+        // Calculate the value of the Lanczos interpolation function for the
+        // required range
+        var sum = 0;
+        for (var i = start; i &lt;= end; i++) {
+            sum += (audioData[i] || 0) * lanczos(index - i, LANCZOS_WINDOW_SIZE);
+        }
+
+        return sum;
+
+    };
+
+    /**
+     * Converts the given AudioBuffer into an audio packet, ready for streaming
+     * along the underlying output stream. Unlike the raw audio packets used by
+     * this audio recorder, AudioBuffers require floating point samples and are
+     * split into isolated planes of channel-specific data.
+     *
+     * @private
+     * @param {AudioBuffer} audioBuffer
+     *     The Web Audio API AudioBuffer that should be converted to a raw
+     *     audio packet.
+     *
+     * @returns {SampleArray}
+     *     A new raw audio packet containing the audio data from the provided
+     *     AudioBuffer.
+     */
+    var toSampleArray = function toSampleArray(audioBuffer) {
+
+        // Track overall amount of data read
+        var inSamples = audioBuffer.length;
+        readSamples += inSamples;
+
+        // Calculate the total number of samples that should be written as of
+        // the audio data just received and adjust the size of the output
+        // packet accordingly
+        var expectedWrittenSamples = Math.round(readSamples * format.rate / audioBuffer.sampleRate);
+        var outSamples = expectedWrittenSamples - writtenSamples;
+
+        // Update number of samples written
+        writtenSamples += outSamples;
+
+        // Get array for raw PCM storage
+        var data = new SampleArray(outSamples * format.channels);
+
+        // Convert each channel
+        for (var channel = 0; channel &lt; format.channels; channel++) {
+
+            var audioData = audioBuffer.getChannelData(channel);
+
+            // Fill array with data from audio buffer channel
+            var offset = channel;
+            for (var i = 0; i &lt; outSamples; i++) {
+                data[offset] = interpolateSample(audioData, i / (outSamples - 1)) * maxSampleValue;
+                offset += format.channels;
+            }
+
+        }
+
+        return data;
+
+    };
+
+    /**
+     * Requests access to the user's microphone and begins capturing audio. All
+     * received audio data is resampled as necessary and forwarded to the
+     * Guacamole stream underlying this Guacamole.RawAudioRecorder. This
+     * function must be invoked ONLY ONCE per instance of
+     * Guacamole.RawAudioRecorder.
+     *
+     * @private
+     */
+    var beginAudioCapture = function beginAudioCapture() {
+
+        // Attempt to retrieve an audio input stream from the browser
+        navigator.mediaDevices.getUserMedia({ 'audio' : true }, function streamReceived(stream) {
+
+            // Create processing node which receives appropriately-sized audio buffers
+            processor = context.createScriptProcessor(BUFFER_SIZE, format.channels, format.channels);
+            processor.connect(context.destination);
+
+            // Send blobs when audio buffers are received
+            processor.onaudioprocess = function processAudio(e) {
+                writer.sendData(toSampleArray(e.inputBuffer).buffer);
+            };
+
+            // Connect processing node to user's audio input source
+            source = context.createMediaStreamSource(stream);
+            source.connect(processor);
+
+            // Save stream for later cleanup
+            mediaStream = stream;
+
+        }, function streamDenied() {
+
+            // Simply end stream if audio access is not allowed
+            writer.sendEnd();
+
+            // Notify of closure
+            if (recorder.onerror)
+                recorder.onerror();
+
+        });
+
+    };
+
+    /**
+     * Stops capturing audio, if the capture has started, freeing all associated
+     * resources. If the capture has not started, this function simply ends the
+     * underlying Guacamole stream.
+     *
+     * @private
+     */
+    var stopAudioCapture = function stopAudioCapture() {
+
+        // Disconnect media source node from script processor
+        if (source)
+            source.disconnect();
+
+        // Disconnect associated script processor node
+        if (processor)
+            processor.disconnect();
+
+        // Stop capture
+        if (mediaStream) {
+            var tracks = mediaStream.getTracks();
+            for (var i = 0; i &lt; tracks.length; i++)
+                tracks[i].stop();
+        }
+
+        // Remove references to now-unneeded components
+        processor = null;
+        source = null;
+        mediaStream = null;
+
+        // End stream
+        writer.sendEnd();
+
+    };
+
+    // Once audio stream is successfully open, request and begin reading audio
+    writer.onack = function audioStreamAcknowledged(status) {
+
+        // Begin capture if successful response and not yet started
+        if (status.code === Guacamole.Status.Code.SUCCESS &amp;&amp; !mediaStream)
+            beginAudioCapture();
+
+        // Otherwise stop capture and cease handling any further acks
+        else {
+
+            // Stop capturing audio
+            stopAudioCapture();
+            writer.onack = null;
+
+            // Notify if stream has closed normally
+            if (status.code === Guacamole.Status.Code.RESOURCE_CLOSED) {
+                if (recorder.onclose)
+                    recorder.onclose();
+            }
+
+            // Otherwise notify of closure due to error
+            else {
+                if (recorder.onerror)
+                    recorder.onerror();
+            }
+
+        }
+
+    };
+
+};
+
+Guacamole.RawAudioRecorder.prototype = new Guacamole.AudioRecorder();
+
+/**
+ * Determines whether the given mimetype is supported by
+ * Guacamole.RawAudioRecorder.
+ *
+ * @param {String} mimetype
+ *     The mimetype to check.
+ *
+ * @returns {Boolean}
+ *     true if the given mimetype is supported by Guacamole.RawAudioRecorder,
+ *     false otherwise.
+ */
+Guacamole.RawAudioRecorder.isSupportedType = function isSupportedType(mimetype) {
+
+    // No supported types if no Web Audio API
+    if (!Guacamole.AudioContextFactory.getAudioContext())
+        return false;
+
+    return Guacamole.RawAudioFormat.parse(mimetype) !== null;
+
+};
+
+/**
+ * Returns a list of all mimetypes supported by Guacamole.RawAudioRecorder. Only
+ * the core mimetypes themselves will be listed. Any mimetype parameters, even
+ * required ones, will not be included in the list. For example, "audio/L8" is
+ * a raw audio mimetype that may be supported, but it is invalid without
+ * additional parameters. Something like "audio/L8;rate=44100" would be valid,
+ * however (see https://tools.ietf.org/html/rfc4856).
+ *
+ * @returns {String[]}
+ *     A list of all mimetypes supported by Guacamole.RawAudioRecorder,
+ *     excluding any parameters. If the necessary JavaScript APIs for recording
+ *     raw audio are absent, this list will be empty.
+ */
+Guacamole.RawAudioRecorder.getSupportedTypes = function getSupportedTypes() {
+
+    // No supported types if no Web Audio API
+    if (!Guacamole.AudioContextFactory.getAudioContext())
+        return [];
+
+    // We support 8-bit and 16-bit raw PCM
+    return [
+        'audio/L8',
+        'audio/L16'
+    ];
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/BlobReader.js.html b/content/doc/1.1.0/guacamole-common-js/BlobReader.js.html
new file mode 100644
index 0000000..a582911
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/BlobReader.js.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: BlobReader.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: BlobReader.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * A reader which automatically handles the given input stream, assembling all
+ * received blobs into a single blob by appending them to each other in order.
+ * Note that this object will overwrite any installed event handlers on the
+ * given Guacamole.InputStream.
+ * 
+ * @constructor
+ * @param {Guacamole.InputStream} stream The stream that data will be read
+ *                                       from.
+ * @param {String} mimetype The mimetype of the blob being built.
+ */
+Guacamole.BlobReader = function(stream, mimetype) {
+
+    /**
+     * Reference to this Guacamole.InputStream.
+     * @private
+     */
+    var guac_reader = this;
+
+    /**
+     * The length of this Guacamole.InputStream in bytes.
+     * @private
+     */
+    var length = 0;
+
+    // Get blob builder
+    var blob_builder;
+    if      (window.BlobBuilder)       blob_builder = new BlobBuilder();
+    else if (window.WebKitBlobBuilder) blob_builder = new WebKitBlobBuilder();
+    else if (window.MozBlobBuilder)    blob_builder = new MozBlobBuilder();
+    else
+        blob_builder = new (function() {
+
+            var blobs = [];
+
+            /** @ignore */
+            this.append = function(data) {
+                blobs.push(new Blob([data], {"type": mimetype}));
+            };
+
+            /** @ignore */
+            this.getBlob = function() {
+                return new Blob(blobs, {"type": mimetype});
+            };
+
+        })();
+
+    // Append received blobs
+    stream.onblob = function(data) {
+
+        // Convert to ArrayBuffer
+        var binary = window.atob(data);
+        var arrayBuffer = new ArrayBuffer(binary.length);
+        var bufferView = new Uint8Array(arrayBuffer);
+
+        for (var i=0; i&lt;binary.length; i++)
+            bufferView[i] = binary.charCodeAt(i);
+
+        blob_builder.append(arrayBuffer);
+        length += arrayBuffer.byteLength;
+
+        // Call handler, if present
+        if (guac_reader.onprogress)
+            guac_reader.onprogress(arrayBuffer.byteLength);
+
+        // Send success response
+        stream.sendAck("OK", 0x0000);
+
+    };
+
+    // Simply call onend when end received
+    stream.onend = function() {
+        if (guac_reader.onend)
+            guac_reader.onend();
+    };
+
+    /**
+     * Returns the current length of this Guacamole.InputStream, in bytes.
+     * @return {Number} The current length of this Guacamole.InputStream.
+     */
+    this.getLength = function() {
+        return length;
+    };
+
+    /**
+     * Returns the contents of this Guacamole.BlobReader as a Blob.
+     * @return {Blob} The contents of this Guacamole.BlobReader.
+     */
+    this.getBlob = function() {
+        return blob_builder.getBlob();
+    };
+
+    /**
+     * Fired once for every blob of data received.
+     * 
+     * @event
+     * @param {Number} length The number of bytes received.
+     */
+    this.onprogress = null;
+
+    /**
+     * Fired once this stream is finished and no further data will be written.
+     * @event
+     */
+    this.onend = null;
+
+};</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/BlobWriter.js.html b/content/doc/1.1.0/guacamole-common-js/BlobWriter.js.html
new file mode 100644
index 0000000..d9f7878
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/BlobWriter.js.html
@@ -0,0 +1,306 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: BlobWriter.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: BlobWriter.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * A writer which automatically writes to the given output stream with the
+ * contents of provided Blob objects.
+ *
+ * @constructor
+ * @param {Guacamole.OutputStream} stream
+ *     The stream that data will be written to.
+ */
+Guacamole.BlobWriter = function BlobWriter(stream) {
+
+    /**
+     * Reference to this Guacamole.BlobWriter.
+     *
+     * @private
+     * @type {Guacamole.BlobWriter}
+     */
+    var guacWriter = this;
+
+    /**
+     * Wrapped Guacamole.ArrayBufferWriter which will be used to send any
+     * provided file data.
+     *
+     * @private
+     * @type {Guacamole.ArrayBufferWriter}
+     */
+    var arrayBufferWriter = new Guacamole.ArrayBufferWriter(stream);
+
+    // Initially, simply call onack for acknowledgements
+    arrayBufferWriter.onack = function(status) {
+        if (guacWriter.onack)
+            guacWriter.onack(status);
+    };
+
+    /**
+     * Browser-independent implementation of Blob.slice() which uses an end
+     * offset to determine the span of the resulting slice, rather than a
+     * length.
+     *
+     * @private
+     * @param {Blob} blob
+     *     The Blob to slice.
+     *
+     * @param {Number} start
+     *     The starting offset of the slice, in bytes, inclusive.
+     *
+     * @param {Number} end
+     *     The ending offset of the slice, in bytes, exclusive.
+     *
+     * @returns {Blob}
+     *     A Blob containing the data within the given Blob starting at
+     *     &lt;code>start&lt;/code> and ending at &lt;code>end - 1&lt;/code>.
+     */
+    var slice = function slice(blob, start, end) {
+
+        // Use prefixed implementations if necessary
+        var sliceImplementation = (
+                blob.slice
+             || blob.webkitSlice
+             || blob.mozSlice
+        ).bind(blob);
+
+        var length = end - start;
+
+        // The old Blob.slice() was length-based (not end-based). Try the
+        // length version first, if the two calls are not equivalent.
+        if (length !== end) {
+
+            // If the result of the slice() call matches the expected length,
+            // trust that result. It must be correct.
+            var sliceResult = sliceImplementation(start, length);
+            if (sliceResult.size === length)
+                return sliceResult;
+
+        }
+
+        // Otherwise, use the most-recent standard: end-based slice()
+        return sliceImplementation(start, end);
+
+    };
+
+    /**
+     * Sends the contents of the given blob over the underlying stream.
+     *
+     * @param {Blob} blob
+     *     The blob to send.
+     */
+    this.sendBlob = function sendBlob(blob) {
+
+        var offset = 0;
+        var reader = new FileReader();
+
+        /**
+         * Reads the next chunk of the blob provided to
+         * [sendBlob()]{@link Guacamole.BlobWriter#sendBlob}. The chunk itself
+         * is read asynchronously, and will not be available until
+         * reader.onload fires.
+         *
+         * @private
+         */
+        var readNextChunk = function readNextChunk() {
+
+            // If no further chunks remain, inform of completion and stop
+            if (offset >= blob.size) {
+
+                // Fire completion event for completed blob
+                if (guacWriter.oncomplete)
+                    guacWriter.oncomplete(blob);
+
+                // No further chunks to read
+                return;
+
+            }
+
+            // Obtain reference to next chunk as a new blob
+            var chunk = slice(blob, offset, offset + arrayBufferWriter.blobLength);
+            offset += arrayBufferWriter.blobLength;
+
+            // Attempt to read the blob contents represented by the blob into
+            // a new array buffer
+            reader.readAsArrayBuffer(chunk);
+
+        };
+
+        // Send each chunk over the stream, continue reading the next chunk
+        reader.onload = function chunkLoadComplete() {
+
+            // Send the successfully-read chunk
+            arrayBufferWriter.sendData(reader.result);
+
+            // Continue sending more chunks after the latest chunk is
+            // acknowledged
+            arrayBufferWriter.onack = function sendMoreChunks(status) {
+
+                if (guacWriter.onack)
+                    guacWriter.onack(status);
+
+                // Abort transfer if an error occurs
+                if (status.isError())
+                    return;
+
+                // Inform of blob upload progress via progress events
+                if (guacWriter.onprogress)
+                    guacWriter.onprogress(blob, offset - arrayBufferWriter.blobLength);
+
+                // Queue the next chunk for reading
+                readNextChunk();
+
+            };
+
+        };
+
+        // If an error prevents further reading, inform of error and stop
+        reader.onerror = function chunkLoadFailed() {
+
+            // Fire error event, including the context of the error
+            if (guacWriter.onerror)
+                guacWriter.onerror(blob, offset, reader.error);
+
+        };
+
+        // Begin reading the first chunk
+        readNextChunk();
+
+    };
+
+    /**
+     * Signals that no further text will be sent, effectively closing the
+     * stream.
+     */
+    this.sendEnd = function sendEnd() {
+        arrayBufferWriter.sendEnd();
+    };
+
+    /**
+     * Fired for received data, if acknowledged by the server.
+     *
+     * @event
+     * @param {Guacamole.Status} status
+     *     The status of the operation.
+     */
+    this.onack = null;
+
+    /**
+     * Fired when an error occurs reading a blob passed to
+     * [sendBlob()]{@link Guacamole.BlobWriter#sendBlob}. The transfer for the
+     * the given blob will cease, but the stream will remain open.
+     *
+     * @event
+     * @param {Blob} blob
+     *     The blob that was being read when the error occurred.
+     *
+     * @param {Number} offset
+     *     The offset of the failed read attempt within the blob, in bytes.
+     *
+     * @param {DOMError} error
+     *     The error that occurred.
+     */
+    this.onerror = null;
+
+    /**
+     * Fired for each successfully-read chunk of data as a blob is being sent
+     * via [sendBlob()]{@link Guacamole.BlobWriter#sendBlob}.
+     *
+     * @event
+     * @param {Blob} blob
+     *     The blob that is being read.
+     *
+     * @param {Number} offset
+     *     The offset of the read that just succeeded.
+     */
+    this.onprogress = null;
+
+    /**
+     * Fired when a blob passed to
+     * [sendBlob()]{@link Guacamole.BlobWriter#sendBlob} has finished being
+     * sent.
+     *
+     * @event
+     * @param {Blob} blob
+     *     The blob that was sent.
+     */
+    this.oncomplete = null;
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/Client.js.html b/content/doc/1.1.0/guacamole-common-js/Client.js.html
new file mode 100644
index 0000000..e1c1f4d
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Client.js.html
@@ -0,0 +1,1751 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: Client.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: Client.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * Guacamole protocol client. Given a {@link Guacamole.Tunnel},
+ * automatically handles incoming and outgoing Guacamole instructions via the
+ * provided tunnel, updating its display using one or more canvas elements.
+ * 
+ * @constructor
+ * @param {Guacamole.Tunnel} tunnel The tunnel to use to send and receive
+ *                                  Guacamole instructions.
+ */
+Guacamole.Client = function(tunnel) {
+
+    var guac_client = this;
+
+    var STATE_IDLE          = 0;
+    var STATE_CONNECTING    = 1;
+    var STATE_WAITING       = 2;
+    var STATE_CONNECTED     = 3;
+    var STATE_DISCONNECTING = 4;
+    var STATE_DISCONNECTED  = 5;
+
+    var currentState = STATE_IDLE;
+    
+    var currentTimestamp = 0;
+    var pingInterval = null;
+
+    /**
+     * Translation from Guacamole protocol line caps to Layer line caps.
+     * @private
+     */
+    var lineCap = {
+        0: "butt",
+        1: "round",
+        2: "square"
+    };
+
+    /**
+     * Translation from Guacamole protocol line caps to Layer line caps.
+     * @private
+     */
+    var lineJoin = {
+        0: "bevel",
+        1: "miter",
+        2: "round"
+    };
+
+    /**
+     * The underlying Guacamole display.
+     *
+     * @private
+     * @type {Guacamole.Display}
+     */
+    var display = new Guacamole.Display();
+
+    /**
+     * All available layers and buffers
+     *
+     * @private
+     * @type {Object.&lt;Number, (Guacamole.Display.VisibleLayer|Guacamole.Layer)>}
+     */
+    var layers = {};
+    
+    /**
+     * All audio players currently in use by the client. Initially, this will
+     * be empty, but audio players may be allocated by the server upon request.
+     *
+     * @private
+     * @type {Object.&lt;Number, Guacamole.AudioPlayer>}
+     */
+    var audioPlayers = {};
+
+    /**
+     * All video players currently in use by the client. Initially, this will
+     * be empty, but video players may be allocated by the server upon request.
+     *
+     * @private
+     * @type {Object.&lt;Number, Guacamole.VideoPlayer>}
+     */
+    var videoPlayers = {};
+
+    // No initial parsers
+    var parsers = [];
+
+    // No initial streams 
+    var streams = [];
+
+    /**
+     * All current objects. The index of each object is dictated by the
+     * Guacamole server.
+     *
+     * @private
+     * @type {Guacamole.Object[]}
+     */
+    var objects = [];
+
+    // Pool of available stream indices
+    var stream_indices = new Guacamole.IntegerPool();
+
+    // Array of allocated output streams by index
+    var output_streams = [];
+
+    function setState(state) {
+        if (state != currentState) {
+            currentState = state;
+            if (guac_client.onstatechange)
+                guac_client.onstatechange(currentState);
+        }
+    }
+
+    function isConnected() {
+        return currentState == STATE_CONNECTED
+            || currentState == STATE_WAITING;
+    }
+
+    /**
+     * Produces an opaque representation of Guacamole.Client state which can be
+     * later imported through a call to importState(). This object is
+     * effectively an independent, compressed snapshot of protocol and display
+     * state. Invoking this function implicitly flushes the display.
+     *
+     * @param {function} callback
+     *     Callback which should be invoked once the state object is ready. The
+     *     state object will be passed to the callback as the sole parameter.
+     *     This callback may be invoked immediately, or later as the display
+     *     finishes rendering and becomes ready.
+     */
+    this.exportState = function exportState(callback) {
+
+        // Start with empty state
+        var state = {
+            'currentState' : currentState,
+            'currentTimestamp' : currentTimestamp,
+            'layers' : {}
+        };
+
+        var layersSnapshot = {};
+
+        // Make a copy of all current layers (protocol state)
+        for (var key in layers) {
+            layersSnapshot[key] = layers[key];
+        }
+
+        // Populate layers once data is available (display state, requires flush)
+        display.flush(function populateLayers() {
+
+            // Export each defined layer/buffer
+            for (var key in layersSnapshot) {
+
+                var index = parseInt(key);
+                var layer = layersSnapshot[key];
+                var canvas = layer.toCanvas();
+
+                // Store layer/buffer dimensions
+                var exportLayer = {
+                    'width'  : layer.width,
+                    'height' : layer.height
+                };
+
+                // Store layer/buffer image data, if it can be generated
+                if (layer.width &amp;&amp; layer.height)
+                    exportLayer.url = canvas.toDataURL('image/png');
+
+                // Add layer properties if not a buffer nor the default layer
+                if (index > 0) {
+                    exportLayer.x = layer.x;
+                    exportLayer.y = layer.y;
+                    exportLayer.z = layer.z;
+                    exportLayer.alpha = layer.alpha;
+                    exportLayer.matrix = layer.matrix;
+                    exportLayer.parent = getLayerIndex(layer.parent);
+                }
+
+                // Store exported layer
+                state.layers[key] = exportLayer;
+
+            }
+
+            // Invoke callback now that the state is ready
+            callback(state);
+
+        });
+
+    };
+
+    /**
+     * Restores Guacamole.Client protocol and display state based on an opaque
+     * object from a prior call to exportState(). The Guacamole.Client instance
+     * used to export that state need not be the same as this instance.
+     *
+     * @param {Object} state
+     *     An opaque representation of Guacamole.Client state from a prior call
+     *     to exportState().
+     *
+     * @param {function} [callback]
+     *     The function to invoke when state has finished being imported. This
+     *     may happen immediately, or later as images within the provided state
+     *     object are loaded.
+     */
+    this.importState = function importState(state, callback) {
+
+        var key;
+        var index;
+
+        currentState = state.currentState;
+        currentTimestamp = state.currentTimestamp;
+
+        // Dispose of all layers
+        for (key in layers) {
+            index = parseInt(key);
+            if (index > 0)
+                display.dispose(layers[key]);
+        }
+
+        layers = {};
+
+        // Import state of each layer/buffer
+        for (key in state.layers) {
+
+            index = parseInt(key);
+
+            var importLayer = state.layers[key];
+            var layer = getLayer(index);
+
+            // Reset layer size
+            display.resize(layer, importLayer.width, importLayer.height);
+
+            // Initialize new layer if it has associated data
+            if (importLayer.url) {
+                display.setChannelMask(layer, Guacamole.Layer.SRC);
+                display.draw(layer, 0, 0, importLayer.url);
+            }
+
+            // Set layer-specific properties if not a buffer nor the default layer
+            if (index > 0 &amp;&amp; importLayer.parent >= 0) {
+
+                // Apply layer position and set parent
+                var parent = getLayer(importLayer.parent);
+                display.move(layer, parent, importLayer.x, importLayer.y, importLayer.z);
+
+                // Set layer transparency
+                display.shade(layer, importLayer.alpha);
+
+                // Apply matrix transform
+                var matrix = importLayer.matrix;
+                display.distort(layer,
+                    matrix[0], matrix[1], matrix[2],
+                    matrix[3], matrix[4], matrix[5]);
+
+            }
+
+        }
+
+        // Flush changes to display
+        display.flush(callback);
+
+    };
+
+    /**
+     * Returns the underlying display of this Guacamole.Client. The display
+     * contains an Element which can be added to the DOM, causing the
+     * display to become visible.
+     * 
+     * @return {Guacamole.Display} The underlying display of this
+     *                             Guacamole.Client.
+     */
+    this.getDisplay = function() {
+        return display;
+    };
+
+    /**
+     * Sends the current size of the screen.
+     * 
+     * @param {Number} width The width of the screen.
+     * @param {Number} height The height of the screen.
+     */
+    this.sendSize = function(width, height) {
+
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        tunnel.sendMessage("size", width, height);
+
+    };
+
+    /**
+     * Sends a key event having the given properties as if the user
+     * pressed or released a key.
+     * 
+     * @param {Boolean} pressed Whether the key is pressed (true) or released
+     *                          (false).
+     * @param {Number} keysym The keysym of the key being pressed or released.
+     */
+    this.sendKeyEvent = function(pressed, keysym) {
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        tunnel.sendMessage("key", keysym, pressed);
+    };
+
+    /**
+     * Sends a mouse event having the properties provided by the given mouse
+     * state.
+     * 
+     * @param {Guacamole.Mouse.State} mouseState The state of the mouse to send
+     *                                           in the mouse event.
+     */
+    this.sendMouseState = function(mouseState) {
+
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        // Update client-side cursor
+        display.moveCursor(
+            Math.floor(mouseState.x),
+            Math.floor(mouseState.y)
+        );
+
+        // Build mask
+        var buttonMask = 0;
+        if (mouseState.left)   buttonMask |= 1;
+        if (mouseState.middle) buttonMask |= 2;
+        if (mouseState.right)  buttonMask |= 4;
+        if (mouseState.up)     buttonMask |= 8;
+        if (mouseState.down)   buttonMask |= 16;
+
+        // Send message
+        tunnel.sendMessage("mouse", Math.floor(mouseState.x), Math.floor(mouseState.y), buttonMask);
+    };
+
+    /**
+     * Allocates an available stream index and creates a new
+     * Guacamole.OutputStream using that index, associating the resulting
+     * stream with this Guacamole.Client. Note that this stream will not yet
+     * exist as far as the other end of the Guacamole connection is concerned.
+     * Streams exist within the Guacamole protocol only when referenced by an
+     * instruction which creates the stream, such as a "clipboard", "file", or
+     * "pipe" instruction.
+     *
+     * @returns {Guacamole.OutputStream}
+     *     A new Guacamole.OutputStream with a newly-allocated index and
+     *     associated with this Guacamole.Client.
+     */
+    this.createOutputStream = function createOutputStream() {
+
+        // Allocate index
+        var index = stream_indices.next();
+
+        // Return new stream
+        var stream = output_streams[index] = new Guacamole.OutputStream(guac_client, index);
+        return stream;
+
+    };
+
+    /**
+     * Opens a new audio stream for writing, where audio data having the give
+     * mimetype will be sent along the returned stream. The instruction
+     * necessary to create this stream will automatically be sent.
+     *
+     * @param {String} mimetype
+     *     The mimetype of the audio data that will be sent along the returned
+     *     stream.
+     *
+     * @return {Guacamole.OutputStream}
+     *     The created audio stream.
+     */
+    this.createAudioStream = function(mimetype) {
+
+        // Allocate and associate stream with audio metadata
+        var stream = guac_client.createOutputStream();
+        tunnel.sendMessage("audio", stream.index, mimetype);
+        return stream;
+
+    };
+
+    /**
+     * Opens a new file for writing, having the given index, mimetype and
+     * filename. The instruction necessary to create this stream will
+     * automatically be sent.
+     *
+     * @param {String} mimetype The mimetype of the file being sent.
+     * @param {String} filename The filename of the file being sent.
+     * @return {Guacamole.OutputStream} The created file stream.
+     */
+    this.createFileStream = function(mimetype, filename) {
+
+        // Allocate and associate stream with file metadata
+        var stream = guac_client.createOutputStream();
+        tunnel.sendMessage("file", stream.index, mimetype, filename);
+        return stream;
+
+    };
+
+    /**
+     * Opens a new pipe for writing, having the given name and mimetype. The
+     * instruction necessary to create this stream will automatically be sent.
+     *
+     * @param {String} mimetype The mimetype of the data being sent.
+     * @param {String} name The name of the pipe.
+     * @return {Guacamole.OutputStream} The created file stream.
+     */
+    this.createPipeStream = function(mimetype, name) {
+
+        // Allocate and associate stream with pipe metadata
+        var stream = guac_client.createOutputStream();
+        tunnel.sendMessage("pipe", stream.index, mimetype, name);
+        return stream;
+
+    };
+
+    /**
+     * Opens a new clipboard object for writing, having the given mimetype. The
+     * instruction necessary to create this stream will automatically be sent.
+     *
+     * @param {String} mimetype The mimetype of the data being sent.
+     * @param {String} name The name of the pipe.
+     * @return {Guacamole.OutputStream} The created file stream.
+     */
+    this.createClipboardStream = function(mimetype) {
+
+        // Allocate and associate stream with clipboard metadata
+        var stream = guac_client.createOutputStream();
+        tunnel.sendMessage("clipboard", stream.index, mimetype);
+        return stream;
+
+    };
+
+    /**
+     * Opens a new argument value stream for writing, having the given
+     * parameter name and mimetype, requesting that the connection parameter
+     * with the given name be updated to the value described by the contents
+     * of the following stream. The instruction necessary to create this stream
+     * will automatically be sent.
+     *
+     * @param {String} mimetype
+     *     The mimetype of the data being sent.
+     *
+     * @param {String} name
+     *     The name of the connection parameter to attempt to update.
+     *
+     * @return {Guacamole.OutputStream}
+     *     The created argument value stream.
+     */
+    this.createArgumentValueStream = function createArgumentValueStream(mimetype, name) {
+
+        // Allocate and associate stream with argument value metadata
+        var stream = guac_client.createOutputStream();
+        tunnel.sendMessage("argv", stream.index, mimetype, name);
+        return stream;
+
+    };
+
+    /**
+     * Creates a new output stream associated with the given object and having
+     * the given mimetype and name. The legality of a mimetype and name is
+     * dictated by the object itself. The instruction necessary to create this
+     * stream will automatically be sent.
+     *
+     * @param {Number} index
+     *     The index of the object for which the output stream is being
+     *     created.
+     *
+     * @param {String} mimetype
+     *     The mimetype of the data which will be sent to the output stream.
+     *
+     * @param {String} name
+     *     The defined name of an output stream within the given object.
+     *
+     * @returns {Guacamole.OutputStream}
+     *     An output stream which will write blobs to the named output stream
+     *     of the given object.
+     */
+    this.createObjectOutputStream = function createObjectOutputStream(index, mimetype, name) {
+
+        // Allocate and ssociate stream with object metadata
+        var stream = guac_client.createOutputStream();
+        tunnel.sendMessage("put", index, stream.index, mimetype, name);
+        return stream;
+
+    };
+
+    /**
+     * Requests read access to the input stream having the given name. If
+     * successful, a new input stream will be created.
+     *
+     * @param {Number} index
+     *     The index of the object from which the input stream is being
+     *     requested.
+     *
+     * @param {String} name
+     *     The name of the input stream to request.
+     */
+    this.requestObjectInputStream = function requestObjectInputStream(index, name) {
+
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        tunnel.sendMessage("get", index, name);
+    };
+
+    /**
+     * Acknowledge receipt of a blob on the stream with the given index.
+     * 
+     * @param {Number} index The index of the stream associated with the
+     *                       received blob.
+     * @param {String} message A human-readable message describing the error
+     *                         or status.
+     * @param {Number} code The error code, if any, or 0 for success.
+     */
+    this.sendAck = function(index, message, code) {
+
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        tunnel.sendMessage("ack", index, message, code);
+    };
+
+    /**
+     * Given the index of a file, writes a blob of data to that file.
+     * 
+     * @param {Number} index The index of the file to write to.
+     * @param {String} data Base64-encoded data to write to the file.
+     */
+    this.sendBlob = function(index, data) {
+
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        tunnel.sendMessage("blob", index, data);
+    };
+
+    /**
+     * Marks a currently-open stream as complete. The other end of the
+     * Guacamole connection will be notified via an "end" instruction that the
+     * stream is closed, and the index will be made available for reuse in
+     * future streams.
+     * 
+     * @param {Number} index
+     *     The index of the stream to end.
+     */
+    this.endStream = function(index) {
+
+        // Do not send requests if not connected
+        if (!isConnected())
+            return;
+
+        // Explicitly close stream by sending "end" instruction
+        tunnel.sendMessage("end", index);
+
+        // Free associated index and stream if they exist
+        if (output_streams[index]) {
+            stream_indices.free(index);
+            delete output_streams[index];
+        }
+
+    };
+
+    /**
+     * Fired whenever the state of this Guacamole.Client changes.
+     * 
+     * @event
+     * @param {Number} state The new state of the client.
+     */
+    this.onstatechange = null;
+
+    /**
+     * Fired when the remote client sends a name update.
+     * 
+     * @event
+     * @param {String} name The new name of this client.
+     */
+    this.onname = null;
+
+    /**
+     * Fired when an error is reported by the remote client, and the connection
+     * is being closed.
+     * 
+     * @event
+     * @param {Guacamole.Status} status A status object which describes the
+     *                                  error.
+     */
+    this.onerror = null;
+
+    /**
+     * Fired when a audio stream is created. The stream provided to this event
+     * handler will contain its own event handlers for received data.
+     *
+     * @event
+     * @param {Guacamole.InputStream} stream
+     *     The stream that will receive audio data from the server.
+     *
+     * @param {String} mimetype
+     *     The mimetype of the audio data which will be received.
+     *
+     * @return {Guacamole.AudioPlayer}
+     *     An object which implements the Guacamole.AudioPlayer interface and
+     *     has been initialied to play the data in the provided stream, or null
+     *     if the built-in audio players of the Guacamole client should be
+     *     used.
+     */
+    this.onaudio = null;
+
+    /**
+     * Fired when a video stream is created. The stream provided to this event
+     * handler will contain its own event handlers for received data.
+     *
+     * @event
+     * @param {Guacamole.InputStream} stream
+     *     The stream that will receive video data from the server.
+     *
+     * @param {Guacamole.Display.VisibleLayer} layer
+     *     The destination layer on which the received video data should be
+     *     played. It is the responsibility of the Guacamole.VideoPlayer
+     *     implementation to play the received data within this layer.
+     *
+     * @param {String} mimetype
+     *     The mimetype of the video data which will be received.
+     *
+     * @return {Guacamole.VideoPlayer}
+     *     An object which implements the Guacamole.VideoPlayer interface and
+     *     has been initialied to play the data in the provided stream, or null
+     *     if the built-in video players of the Guacamole client should be
+     *     used.
+     */
+    this.onvideo = null;
+
+    /**
+     * Fired when the current value of a connection parameter is being exposed
+     * by the server.
+     *
+     * @event
+     * @param {Guacamole.InputStream} stream
+     *     The stream that will receive connection parameter data from the
+     *     server.
+     *
+     * @param {String} mimetype
+     *     The mimetype of the data which will be received.
+     *
+     * @param {String} name
+     *     The name of the connection parameter whose value is being exposed.
+     */
+    this.onargv = null;
+
+    /**
+     * Fired when the clipboard of the remote client is changing.
+     * 
+     * @event
+     * @param {Guacamole.InputStream} stream The stream that will receive
+     *                                       clipboard data from the server.
+     * @param {String} mimetype The mimetype of the data which will be received.
+     */
+    this.onclipboard = null;
+
+    /**
+     * Fired when a file stream is created. The stream provided to this event
+     * handler will contain its own event handlers for received data.
+     * 
+     * @event
+     * @param {Guacamole.InputStream} stream The stream that will receive data
+     *                                       from the server.
+     * @param {String} mimetype The mimetype of the file received.
+     * @param {String} filename The name of the file received.
+     */
+    this.onfile = null;
+
+    /**
+     * Fired when a filesystem object is created. The object provided to this
+     * event handler will contain its own event handlers and functions for
+     * requesting and handling data.
+     *
+     * @event
+     * @param {Guacamole.Object} object
+     *     The created filesystem object.
+     *
+     * @param {String} name
+     *     The name of the filesystem.
+     */
+    this.onfilesystem = null;
+
+    /**
+     * Fired when a pipe stream is created. The stream provided to this event
+     * handler will contain its own event handlers for received data;
+     * 
+     * @event
+     * @param {Guacamole.InputStream} stream The stream that will receive data
+     *                                       from the server.
+     * @param {String} mimetype The mimetype of the data which will be received.
+     * @param {String} name The name of the pipe.
+     */
+    this.onpipe = null;
+
+    /**
+     * Fired whenever a sync instruction is received from the server, indicating
+     * that the server is finished processing any input from the client and
+     * has sent any results.
+     * 
+     * @event
+     * @param {Number} timestamp The timestamp associated with the sync
+     *                           instruction.
+     */
+    this.onsync = null;
+
+    /**
+     * Returns the layer with the given index, creating it if necessary.
+     * Positive indices refer to visible layers, an index of zero refers to
+     * the default layer, and negative indices refer to buffers.
+     *
+     * @private
+     * @param {Number} index
+     *     The index of the layer to retrieve.
+     *
+     * @return {Guacamole.Display.VisibleLayer|Guacamole.Layer}
+     *     The layer having the given index.
+     */
+    var getLayer = function getLayer(index) {
+
+        // Get layer, create if necessary
+        var layer = layers[index];
+        if (!layer) {
+
+            // Create layer based on index
+            if (index === 0)
+                layer = display.getDefaultLayer();
+            else if (index > 0)
+                layer = display.createLayer();
+            else
+                layer = display.createBuffer();
+                
+            // Add new layer
+            layers[index] = layer;
+
+        }
+
+        return layer;
+
+    };
+
+    /**
+     * Returns the index passed to getLayer() when the given layer was created.
+     * Positive indices refer to visible layers, an index of zero refers to the
+     * default layer, and negative indices refer to buffers.
+     *
+     * @param {Guacamole.Display.VisibleLayer|Guacamole.Layer} layer
+     *     The layer whose index should be determined.
+     *
+     * @returns {Number}
+     *     The index of the given layer, or null if no such layer is associated
+     *     with this client.
+     */
+    var getLayerIndex = function getLayerIndex(layer) {
+
+        // Avoid searching if there clearly is no such layer
+        if (!layer)
+            return null;
+
+        // Search through each layer, returning the index of the given layer
+        // once found
+        for (var key in layers) {
+            if (layer === layers[key])
+                return parseInt(key);
+        }
+
+        // Otherwise, no such index
+        return null;
+
+    };
+
+    function getParser(index) {
+
+        var parser = parsers[index];
+
+        // If parser not yet created, create it, and tie to the
+        // oninstruction handler of the tunnel.
+        if (parser == null) {
+            parser = parsers[index] = new Guacamole.Parser();
+            parser.oninstruction = tunnel.oninstruction;
+        }
+
+        return parser;
+
+    }
+
+    /**
+     * Handlers for all defined layer properties.
+     * @private
+     */
+    var layerPropertyHandlers = {
+
+        "miter-limit": function(layer, value) {
+            display.setMiterLimit(layer, parseFloat(value));
+        }
+
+    };
+    
+    /**
+     * Handlers for all instruction opcodes receivable by a Guacamole protocol
+     * client.
+     * @private
+     */
+    var instructionHandlers = {
+
+        "ack": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var reason = parameters[1];
+            var code = parseInt(parameters[2]);
+
+            // Get stream
+            var stream = output_streams[stream_index];
+            if (stream) {
+
+                // Signal ack if handler defined
+                if (stream.onack)
+                    stream.onack(new Guacamole.Status(code, reason));
+
+                // If code is an error, invalidate stream if not already
+                // invalidated by onack handler
+                if (code >= 0x0100 &amp;&amp; output_streams[stream_index] === stream) {
+                    stream_indices.free(stream_index);
+                    delete output_streams[stream_index];
+                }
+
+            }
+
+        },
+
+        "arc": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var x = parseInt(parameters[1]);
+            var y = parseInt(parameters[2]);
+            var radius = parseInt(parameters[3]);
+            var startAngle = parseFloat(parameters[4]);
+            var endAngle = parseFloat(parameters[5]);
+            var negative = parseInt(parameters[6]);
+
+            display.arc(layer, x, y, radius, startAngle, endAngle, negative != 0);
+
+        },
+
+        "argv": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var mimetype = parameters[1];
+            var name = parameters[2];
+
+            // Create stream
+            if (guac_client.onargv) {
+                var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
+                guac_client.onargv(stream, mimetype, name);
+            }
+
+            // Otherwise, unsupported
+            else
+                guac_client.sendAck(stream_index, "Receiving argument values unsupported", 0x0100);
+
+        },
+
+        "audio": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var mimetype = parameters[1];
+
+            // Create stream 
+            var stream = streams[stream_index] =
+                    new Guacamole.InputStream(guac_client, stream_index);
+
+            // Get player instance via callback
+            var audioPlayer = null;
+            if (guac_client.onaudio)
+                audioPlayer = guac_client.onaudio(stream, mimetype);
+
+            // If unsuccessful, try to use a default implementation
+            if (!audioPlayer)
+                audioPlayer = Guacamole.AudioPlayer.getInstance(stream, mimetype);
+
+            // If we have successfully retrieved an audio player, send success response
+            if (audioPlayer) {
+                audioPlayers[stream_index] = audioPlayer;
+                guac_client.sendAck(stream_index, "OK", 0x0000);
+            }
+
+            // Otherwise, mimetype must be unsupported
+            else
+                guac_client.sendAck(stream_index, "BAD TYPE", 0x030F);
+
+        },
+
+        "blob": function(parameters) {
+
+            // Get stream 
+            var stream_index = parseInt(parameters[0]);
+            var data = parameters[1];
+            var stream = streams[stream_index];
+
+            // Write data
+            if (stream &amp;&amp; stream.onblob)
+                stream.onblob(data);
+
+        },
+
+        "body" : function handleBody(parameters) {
+
+            // Get object
+            var objectIndex = parseInt(parameters[0]);
+            var object = objects[objectIndex];
+
+            var streamIndex = parseInt(parameters[1]);
+            var mimetype = parameters[2];
+            var name = parameters[3];
+
+            // Create stream if handler defined
+            if (object &amp;&amp; object.onbody) {
+                var stream = streams[streamIndex] = new Guacamole.InputStream(guac_client, streamIndex);
+                object.onbody(stream, mimetype, name);
+            }
+
+            // Otherwise, unsupported
+            else
+                guac_client.sendAck(streamIndex, "Receipt of body unsupported", 0x0100);
+
+        },
+
+        "cfill": function(parameters) {
+
+            var channelMask = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var r = parseInt(parameters[2]);
+            var g = parseInt(parameters[3]);
+            var b = parseInt(parameters[4]);
+            var a = parseInt(parameters[5]);
+
+            display.setChannelMask(layer, channelMask);
+            display.fillColor(layer, r, g, b, a);
+
+        },
+
+        "clip": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+
+            display.clip(layer);
+
+        },
+
+        "clipboard": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var mimetype = parameters[1];
+
+            // Create stream 
+            if (guac_client.onclipboard) {
+                var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
+                guac_client.onclipboard(stream, mimetype);
+            }
+
+            // Otherwise, unsupported
+            else
+                guac_client.sendAck(stream_index, "Clipboard unsupported", 0x0100);
+
+        },
+
+        "close": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+
+            display.close(layer);
+
+        },
+
+        "copy": function(parameters) {
+
+            var srcL = getLayer(parseInt(parameters[0]));
+            var srcX = parseInt(parameters[1]);
+            var srcY = parseInt(parameters[2]);
+            var srcWidth = parseInt(parameters[3]);
+            var srcHeight = parseInt(parameters[4]);
+            var channelMask = parseInt(parameters[5]);
+            var dstL = getLayer(parseInt(parameters[6]));
+            var dstX = parseInt(parameters[7]);
+            var dstY = parseInt(parameters[8]);
+
+            display.setChannelMask(dstL, channelMask);
+            display.copy(srcL, srcX, srcY, srcWidth, srcHeight, 
+                         dstL, dstX, dstY);
+
+        },
+
+        "cstroke": function(parameters) {
+
+            var channelMask = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var cap = lineCap[parseInt(parameters[2])];
+            var join = lineJoin[parseInt(parameters[3])];
+            var thickness = parseInt(parameters[4]);
+            var r = parseInt(parameters[5]);
+            var g = parseInt(parameters[6]);
+            var b = parseInt(parameters[7]);
+            var a = parseInt(parameters[8]);
+
+            display.setChannelMask(layer, channelMask);
+            display.strokeColor(layer, cap, join, thickness, r, g, b, a);
+
+        },
+
+        "cursor": function(parameters) {
+
+            var cursorHotspotX = parseInt(parameters[0]);
+            var cursorHotspotY = parseInt(parameters[1]);
+            var srcL = getLayer(parseInt(parameters[2]));
+            var srcX = parseInt(parameters[3]);
+            var srcY = parseInt(parameters[4]);
+            var srcWidth = parseInt(parameters[5]);
+            var srcHeight = parseInt(parameters[6]);
+
+            display.setCursor(cursorHotspotX, cursorHotspotY,
+                              srcL, srcX, srcY, srcWidth, srcHeight);
+
+        },
+
+        "curve": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var cp1x = parseInt(parameters[1]);
+            var cp1y = parseInt(parameters[2]);
+            var cp2x = parseInt(parameters[3]);
+            var cp2y = parseInt(parameters[4]);
+            var x = parseInt(parameters[5]);
+            var y = parseInt(parameters[6]);
+
+            display.curveTo(layer, cp1x, cp1y, cp2x, cp2y, x, y);
+
+        },
+
+        "disconnect" : function handleDisconnect(parameters) {
+
+            // Explicitly tear down connection
+            guac_client.disconnect();
+
+        },
+
+        "dispose": function(parameters) {
+            
+            var layer_index = parseInt(parameters[0]);
+
+            // If visible layer, remove from parent
+            if (layer_index > 0) {
+
+                // Remove from parent
+                var layer = getLayer(layer_index);
+                display.dispose(layer);
+
+                // Delete reference
+                delete layers[layer_index];
+
+            }
+
+            // If buffer, just delete reference
+            else if (layer_index &lt; 0)
+                delete layers[layer_index];
+
+            // Attempting to dispose the root layer currently has no effect.
+
+        },
+
+        "distort": function(parameters) {
+
+            var layer_index = parseInt(parameters[0]);
+            var a = parseFloat(parameters[1]);
+            var b = parseFloat(parameters[2]);
+            var c = parseFloat(parameters[3]);
+            var d = parseFloat(parameters[4]);
+            var e = parseFloat(parameters[5]);
+            var f = parseFloat(parameters[6]);
+
+            // Only valid for visible layers (not buffers)
+            if (layer_index >= 0) {
+                var layer = getLayer(layer_index);
+                display.distort(layer, a, b, c, d, e, f);
+            }
+
+        },
+ 
+        "error": function(parameters) {
+
+            var reason = parameters[0];
+            var code = parseInt(parameters[1]);
+
+            // Call handler if defined
+            if (guac_client.onerror)
+                guac_client.onerror(new Guacamole.Status(code, reason));
+
+            guac_client.disconnect();
+
+        },
+
+        "end": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+
+            // Get stream
+            var stream = streams[stream_index];
+            if (stream) {
+
+                // Signal end of stream if handler defined
+                if (stream.onend)
+                    stream.onend();
+
+                // Invalidate stream
+                delete streams[stream_index];
+
+            }
+
+        },
+
+        "file": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var mimetype = parameters[1];
+            var filename = parameters[2];
+
+            // Create stream 
+            if (guac_client.onfile) {
+                var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
+                guac_client.onfile(stream, mimetype, filename);
+            }
+
+            // Otherwise, unsupported
+            else
+                guac_client.sendAck(stream_index, "File transfer unsupported", 0x0100);
+
+        },
+
+        "filesystem" : function handleFilesystem(parameters) {
+
+            var objectIndex = parseInt(parameters[0]);
+            var name = parameters[1];
+
+            // Create object, if supported
+            if (guac_client.onfilesystem) {
+                var object = objects[objectIndex] = new Guacamole.Object(guac_client, objectIndex);
+                guac_client.onfilesystem(object, name);
+            }
+
+            // If unsupported, simply ignore the availability of the filesystem
+
+        },
+
+        "identity": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+
+            display.setTransform(layer, 1, 0, 0, 1, 0, 0);
+
+        },
+
+        "img": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var channelMask = parseInt(parameters[1]);
+            var layer = getLayer(parseInt(parameters[2]));
+            var mimetype = parameters[3];
+            var x = parseInt(parameters[4]);
+            var y = parseInt(parameters[5]);
+
+            // Create stream
+            var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
+            var reader = new Guacamole.DataURIReader(stream, mimetype);
+
+            // Draw image when stream is complete
+            reader.onend = function drawImageBlob() {
+                display.setChannelMask(layer, channelMask);
+                display.draw(layer, x, y, reader.getURI());
+            };
+
+        },
+
+        "jpeg": function(parameters) {
+
+            var channelMask = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var x = parseInt(parameters[2]);
+            var y = parseInt(parameters[3]);
+            var data = parameters[4];
+
+            display.setChannelMask(layer, channelMask);
+            display.draw(layer, x, y, "data:image/jpeg;base64," + data);
+
+        },
+
+        "lfill": function(parameters) {
+
+            var channelMask = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var srcLayer = getLayer(parseInt(parameters[2]));
+
+            display.setChannelMask(layer, channelMask);
+            display.fillLayer(layer, srcLayer);
+
+        },
+
+        "line": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var x = parseInt(parameters[1]);
+            var y = parseInt(parameters[2]);
+
+            display.lineTo(layer, x, y);
+
+        },
+
+        "lstroke": function(parameters) {
+
+            var channelMask = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var srcLayer = getLayer(parseInt(parameters[2]));
+
+            display.setChannelMask(layer, channelMask);
+            display.strokeLayer(layer, srcLayer);
+
+        },
+
+        "mouse" : function handleMouse(parameters) {
+
+            var x = parseInt(parameters[0]);
+            var y = parseInt(parameters[1]);
+
+            // Display and move software cursor to received coordinates
+            display.showCursor(true);
+            display.moveCursor(x, y);
+
+        },
+
+        "move": function(parameters) {
+            
+            var layer_index = parseInt(parameters[0]);
+            var parent_index = parseInt(parameters[1]);
+            var x = parseInt(parameters[2]);
+            var y = parseInt(parameters[3]);
+            var z = parseInt(parameters[4]);
+
+            // Only valid for non-default layers
+            if (layer_index > 0 &amp;&amp; parent_index >= 0) {
+                var layer = getLayer(layer_index);
+                var parent = getLayer(parent_index);
+                display.move(layer, parent, x, y, z);
+            }
+
+        },
+
+        "name": function(parameters) {
+            if (guac_client.onname) guac_client.onname(parameters[0]);
+        },
+
+        "nest": function(parameters) {
+            var parser = getParser(parseInt(parameters[0]));
+            parser.receive(parameters[1]);
+        },
+
+        "pipe": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var mimetype = parameters[1];
+            var name = parameters[2];
+
+            // Create stream 
+            if (guac_client.onpipe) {
+                var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
+                guac_client.onpipe(stream, mimetype, name);
+            }
+
+            // Otherwise, unsupported
+            else
+                guac_client.sendAck(stream_index, "Named pipes unsupported", 0x0100);
+
+        },
+
+        "png": function(parameters) {
+
+            var channelMask = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var x = parseInt(parameters[2]);
+            var y = parseInt(parameters[3]);
+            var data = parameters[4];
+
+            display.setChannelMask(layer, channelMask);
+            display.draw(layer, x, y, "data:image/png;base64," + data);
+
+        },
+
+        "pop": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+
+            display.pop(layer);
+
+        },
+
+        "push": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+
+            display.push(layer);
+
+        },
+ 
+        "rect": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var x = parseInt(parameters[1]);
+            var y = parseInt(parameters[2]);
+            var w = parseInt(parameters[3]);
+            var h = parseInt(parameters[4]);
+
+            display.rect(layer, x, y, w, h);
+
+        },
+        
+        "reset": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+
+            display.reset(layer);
+
+        },
+        
+        "set": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var name = parameters[1];
+            var value = parameters[2];
+
+            // Call property handler if defined
+            var handler = layerPropertyHandlers[name];
+            if (handler)
+                handler(layer, value);
+
+        },
+
+        "shade": function(parameters) {
+            
+            var layer_index = parseInt(parameters[0]);
+            var a = parseInt(parameters[1]);
+
+            // Only valid for visible layers (not buffers)
+            if (layer_index >= 0) {
+                var layer = getLayer(layer_index);
+                display.shade(layer, a);
+            }
+
+        },
+
+        "size": function(parameters) {
+
+            var layer_index = parseInt(parameters[0]);
+            var layer = getLayer(layer_index);
+            var width = parseInt(parameters[1]);
+            var height = parseInt(parameters[2]);
+
+            display.resize(layer, width, height);
+
+        },
+        
+        "start": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var x = parseInt(parameters[1]);
+            var y = parseInt(parameters[2]);
+
+            display.moveTo(layer, x, y);
+
+        },
+
+        "sync": function(parameters) {
+
+            var timestamp = parseInt(parameters[0]);
+
+            // Flush display, send sync when done
+            display.flush(function displaySyncComplete() {
+
+                // Synchronize all audio players
+                for (var index in audioPlayers) {
+                    var audioPlayer = audioPlayers[index];
+                    if (audioPlayer)
+                        audioPlayer.sync();
+                }
+
+                // Send sync response to server
+                if (timestamp !== currentTimestamp) {
+                    tunnel.sendMessage("sync", timestamp);
+                    currentTimestamp = timestamp;
+                }
+
+            });
+
+            // If received first update, no longer waiting.
+            if (currentState === STATE_WAITING)
+                setState(STATE_CONNECTED);
+
+            // Call sync handler if defined
+            if (guac_client.onsync)
+                guac_client.onsync(timestamp);
+
+        },
+
+        "transfer": function(parameters) {
+
+            var srcL = getLayer(parseInt(parameters[0]));
+            var srcX = parseInt(parameters[1]);
+            var srcY = parseInt(parameters[2]);
+            var srcWidth = parseInt(parameters[3]);
+            var srcHeight = parseInt(parameters[4]);
+            var function_index = parseInt(parameters[5]);
+            var dstL = getLayer(parseInt(parameters[6]));
+            var dstX = parseInt(parameters[7]);
+            var dstY = parseInt(parameters[8]);
+
+            /* SRC */
+            if (function_index === 0x3)
+                display.put(srcL, srcX, srcY, srcWidth, srcHeight, 
+                    dstL, dstX, dstY);
+
+            /* Anything else that isn't a NO-OP */
+            else if (function_index !== 0x5)
+                display.transfer(srcL, srcX, srcY, srcWidth, srcHeight, 
+                    dstL, dstX, dstY, Guacamole.Client.DefaultTransferFunction[function_index]);
+
+        },
+
+        "transform": function(parameters) {
+
+            var layer = getLayer(parseInt(parameters[0]));
+            var a = parseFloat(parameters[1]);
+            var b = parseFloat(parameters[2]);
+            var c = parseFloat(parameters[3]);
+            var d = parseFloat(parameters[4]);
+            var e = parseFloat(parameters[5]);
+            var f = parseFloat(parameters[6]);
+
+            display.transform(layer, a, b, c, d, e, f);
+
+        },
+
+        "undefine" : function handleUndefine(parameters) {
+
+            // Get object
+            var objectIndex = parseInt(parameters[0]);
+            var object = objects[objectIndex];
+
+            // Signal end of object definition
+            if (object &amp;&amp; object.onundefine)
+                object.onundefine();
+
+        },
+
+        "video": function(parameters) {
+
+            var stream_index = parseInt(parameters[0]);
+            var layer = getLayer(parseInt(parameters[1]));
+            var mimetype = parameters[2];
+
+            // Create stream
+            var stream = streams[stream_index] =
+                    new Guacamole.InputStream(guac_client, stream_index);
+
+            // Get player instance via callback
+            var videoPlayer = null;
+            if (guac_client.onvideo)
+                videoPlayer = guac_client.onvideo(stream, layer, mimetype);
+
+            // If unsuccessful, try to use a default implementation
+            if (!videoPlayer)
+                videoPlayer = Guacamole.VideoPlayer.getInstance(stream, layer, mimetype);
+
+            // If we have successfully retrieved an video player, send success response
+            if (videoPlayer) {
+                videoPlayers[stream_index] = videoPlayer;
+                guac_client.sendAck(stream_index, "OK", 0x0000);
+            }
+
+            // Otherwise, mimetype must be unsupported
+            else
+                guac_client.sendAck(stream_index, "BAD TYPE", 0x030F);
+
+        }
+
+    };
+
+    tunnel.oninstruction = function(opcode, parameters) {
+
+        var handler = instructionHandlers[opcode];
+        if (handler)
+            handler(parameters);
+
+    };
+
+    /**
+     * Sends a disconnect instruction to the server and closes the tunnel.
+     */
+    this.disconnect = function() {
+
+        // Only attempt disconnection not disconnected.
+        if (currentState != STATE_DISCONNECTED
+                &amp;&amp; currentState != STATE_DISCONNECTING) {
+
+            setState(STATE_DISCONNECTING);
+
+            // Stop ping
+            if (pingInterval)
+                window.clearInterval(pingInterval);
+
+            // Send disconnect message and disconnect
+            tunnel.sendMessage("disconnect");
+            tunnel.disconnect();
+            setState(STATE_DISCONNECTED);
+
+        }
+
+    };
+    
+    /**
+     * Connects the underlying tunnel of this Guacamole.Client, passing the
+     * given arbitrary data to the tunnel during the connection process.
+     *
+     * @param data Arbitrary connection data to be sent to the underlying
+     *             tunnel during the connection process.
+     * @throws {Guacamole.Status} If an error occurs during connection.
+     */
+    this.connect = function(data) {
+
+        setState(STATE_CONNECTING);
+
+        try {
+            tunnel.connect(data);
+        }
+        catch (status) {
+            setState(STATE_IDLE);
+            throw status;
+        }
+
+        // Ping every 5 seconds (ensure connection alive)
+        pingInterval = window.setInterval(function() {
+            tunnel.sendMessage("nop");
+        }, 5000);
+
+        setState(STATE_WAITING);
+    };
+
+};
+
+/**
+ * Map of all Guacamole binary raster operations to transfer functions.
+ * @private
+ */
+Guacamole.Client.DefaultTransferFunction = {
+
+    /* BLACK */
+    0x0: function (src, dst) {
+        dst.red = dst.green = dst.blue = 0x00;
+    },
+
+    /* WHITE */
+    0xF: function (src, dst) {
+        dst.red = dst.green = dst.blue = 0xFF;
+    },
+
+    /* SRC */
+    0x3: function (src, dst) {
+        dst.red   = src.red;
+        dst.green = src.green;
+        dst.blue  = src.blue;
+        dst.alpha = src.alpha;
+    },
+
+    /* DEST (no-op) */
+    0x5: function (src, dst) {
+        // Do nothing
+    },
+
+    /* Invert SRC */
+    0xC: function (src, dst) {
+        dst.red   = 0xFF &amp; ~src.red;
+        dst.green = 0xFF &amp; ~src.green;
+        dst.blue  = 0xFF &amp; ~src.blue;
+        dst.alpha =  src.alpha;
+    },
+    
+    /* Invert DEST */
+    0xA: function (src, dst) {
+        dst.red   = 0xFF &amp; ~dst.red;
+        dst.green = 0xFF &amp; ~dst.green;
+        dst.blue  = 0xFF &amp; ~dst.blue;
+    },
+
+    /* AND */
+    0x1: function (src, dst) {
+        dst.red   =  ( src.red   &amp;  dst.red);
+        dst.green =  ( src.green &amp;  dst.green);
+        dst.blue  =  ( src.blue  &amp;  dst.blue);
+    },
+
+    /* NAND */
+    0xE: function (src, dst) {
+        dst.red   = 0xFF &amp; ~( src.red   &amp;  dst.red);
+        dst.green = 0xFF &amp; ~( src.green &amp;  dst.green);
+        dst.blue  = 0xFF &amp; ~( src.blue  &amp;  dst.blue);
+    },
+
+    /* OR */
+    0x7: function (src, dst) {
+        dst.red   =  ( src.red   |  dst.red);
+        dst.green =  ( src.green |  dst.green);
+        dst.blue  =  ( src.blue  |  dst.blue);
+    },
+
+    /* NOR */
+    0x8: function (src, dst) {
+        dst.red   = 0xFF &amp; ~( src.red   |  dst.red);
+        dst.green = 0xFF &amp; ~( src.green |  dst.green);
+        dst.blue  = 0xFF &amp; ~( src.blue  |  dst.blue);
+    },
+
+    /* XOR */
+    0x6: function (src, dst) {
+        dst.red   =  ( src.red   ^  dst.red);
+        dst.green =  ( src.green ^  dst.green);
+        dst.blue  =  ( src.blue  ^  dst.blue);
+    },
+
+    /* XNOR */
+    0x9: function (src, dst) {
+        dst.red   = 0xFF &amp; ~( src.red   ^  dst.red);
+        dst.green = 0xFF &amp; ~( src.green ^  dst.green);
+        dst.blue  = 0xFF &amp; ~( src.blue  ^  dst.blue);
+    },
+
+    /* AND inverted source */
+    0x4: function (src, dst) {
+        dst.red   =  0xFF &amp; (~src.red   &amp;  dst.red);
+        dst.green =  0xFF &amp; (~src.green &amp;  dst.green);
+        dst.blue  =  0xFF &amp; (~src.blue  &amp;  dst.blue);
+    },
+
+    /* OR inverted source */
+    0xD: function (src, dst) {
+        dst.red   =  0xFF &amp; (~src.red   |  dst.red);
+        dst.green =  0xFF &amp; (~src.green |  dst.green);
+        dst.blue  =  0xFF &amp; (~src.blue  |  dst.blue);
+    },
+
+    /* AND inverted destination */
+    0x2: function (src, dst) {
+        dst.red   =  0xFF &amp; ( src.red   &amp; ~dst.red);
+        dst.green =  0xFF &amp; ( src.green &amp; ~dst.green);
+        dst.blue  =  0xFF &amp; ( src.blue  &amp; ~dst.blue);
+    },
+
+    /* OR inverted destination */
+    0xB: function (src, dst) {
+        dst.red   =  0xFF &amp; ( src.red   | ~dst.red);
+        dst.green =  0xFF &amp; ( src.green | ~dst.green);
+        dst.blue  =  0xFF &amp; ( src.blue  | ~dst.blue);
+    }
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/DataURIReader.js.html b/content/doc/1.1.0/guacamole-common-js/DataURIReader.js.html
new file mode 100644
index 0000000..2c30509
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/DataURIReader.js.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: DataURIReader.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: DataURIReader.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * A reader which automatically handles the given input stream, returning
+ * received blobs as a single data URI built over the course of the stream.
+ * Note that this object will overwrite any installed event handlers on the
+ * given Guacamole.InputStream.
+ * 
+ * @constructor
+ * @param {Guacamole.InputStream} stream
+ *     The stream that data will be read from.
+ */
+Guacamole.DataURIReader = function(stream, mimetype) {
+
+    /**
+     * Reference to this Guacamole.DataURIReader.
+     * @private
+     */
+    var guac_reader = this;
+
+    /**
+     * Current data URI.
+     *
+     * @private
+     * @type {String}
+     */
+    var uri = 'data:' + mimetype + ';base64,';
+
+    // Receive blobs as array buffers
+    stream.onblob = function dataURIReaderBlob(data) {
+
+        // Currently assuming data will ALWAYS be safe to simply append. This
+        // will not be true if the received base64 data encodes a number of
+        // bytes that isn't a multiple of three (as base64 expands in a ratio
+        // of exactly 3:4).
+        uri += data;
+
+    };
+
+    // Simply call onend when end received
+    stream.onend = function dataURIReaderEnd() {
+        if (guac_reader.onend)
+            guac_reader.onend();
+    };
+
+    /**
+     * Returns the data URI of all data received through the underlying stream
+     * thus far.
+     *
+     * @returns {String}
+     *     The data URI of all data received through the underlying stream thus
+     *     far.
+     */
+    this.getURI = function getURI() {
+        return uri;
+    };
+
+    /**
+     * Fired once this stream is finished and no further data will be written.
+     *
+     * @event
+     */
+    this.onend = null;
+
+};</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/Display.js.html b/content/doc/1.1.0/guacamole-common-js/Display.js.html
new file mode 100644
index 0000000..ab16f26
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Display.js.html
@@ -0,0 +1,1543 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: Display.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: Display.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var Guacamole = Guacamole || {};
+
+/**
+ * The Guacamole display. The display does not deal with the Guacamole
+ * protocol, and instead implements a set of graphical operations which
+ * embody the set of operations present in the protocol. The order operations
+ * are executed is guaranteed to be in the same order as their corresponding
+ * functions are called.
+ * 
+ * @constructor
+ */
+Guacamole.Display = function() {
+
+    /**
+     * Reference to this Guacamole.Display.
+     * @private
+     */
+    var guac_display = this;
+
+    var displayWidth = 0;
+    var displayHeight = 0;
+    var displayScale = 1;
+
+    // Create display
+    var display = document.createElement("div");
+    display.style.position = "relative";
+    display.style.width = displayWidth + "px";
+    display.style.height = displayHeight + "px";
+
+    // Ensure transformations on display originate at 0,0
+    display.style.transformOrigin =
+    display.style.webkitTransformOrigin =
+    display.style.MozTransformOrigin =
+    display.style.OTransformOrigin =
+    display.style.msTransformOrigin =
+        "0 0";
+
+    // Create default layer
+    var default_layer = new Guacamole.Display.VisibleLayer(displayWidth, displayHeight);
+
+    // Create cursor layer
+    var cursor = new Guacamole.Display.VisibleLayer(0, 0);
+    cursor.setChannelMask(Guacamole.Layer.SRC);
+
+    // Add default layer and cursor to display
+    display.appendChild(default_layer.getElement());
+    display.appendChild(cursor.getElement());
+
+    // Create bounding div 
+    var bounds = document.createElement("div");
+    bounds.style.position = "relative";
+    bounds.style.width = (displayWidth*displayScale) + "px";
+    bounds.style.height = (displayHeight*displayScale) + "px";
+
+    // Add display to bounds
+    bounds.appendChild(display);
+
+    /**
+     * The X coordinate of the hotspot of the mouse cursor. The hotspot is
+     * the relative location within the image of the mouse cursor at which
+     * each click occurs.
+     * 
+     * @type {Number}
+     */
+    this.cursorHotspotX = 0;
+
+    /**
+     * The Y coordinate of the hotspot of the mouse cursor. The hotspot is
+     * the relative location within the image of the mouse cursor at which
+     * each click occurs.
+     * 
+     * @type {Number}
+     */
+    this.cursorHotspotY = 0;
+
+    /**
+     * The current X coordinate of the local mouse cursor. This is not
+     * necessarily the location of the actual mouse - it refers only to
+     * the location of the cursor image within the Guacamole display, as
+     * last set by moveCursor().
+     * 
+     * @type {Number}
+     */
+    this.cursorX = 0;
+
+    /**
+     * The current X coordinate of the local mouse cursor. This is not
+     * necessarily the location of the actual mouse - it refers only to
+     * the location of the cursor image within the Guacamole display, as
+     * last set by moveCursor().
+     * 
+     * @type {Number}
+     */
+    this.cursorY = 0;
+
+    /**
+     * Fired when the default layer (and thus the entire Guacamole display)
+     * is resized.
+     * 
+     * @event
+     * @param {Number} width The new width of the Guacamole display.
+     * @param {Number} height The new height of the Guacamole display.
+     */
+    this.onresize = null;
+
+    /**
+     * Fired whenever the local cursor image is changed. This can be used to
+     * implement special handling of the client-side cursor, or to override
+     * the default use of a software cursor layer.
+     * 
+     * @event
+     * @param {HTMLCanvasElement} canvas The cursor image.
+     * @param {Number} x The X-coordinate of the cursor hotspot.
+     * @param {Number} y The Y-coordinate of the cursor hotspot.
+     */
+    this.oncursor = null;
+
+    /**
+     * The queue of all pending Tasks. Tasks will be run in order, with new
+     * tasks added at the end of the queue and old tasks removed from the
+     * front of the queue (FIFO). These tasks will eventually be grouped
+     * into a Frame.
+     * @private
+     * @type {Task[]}
+     */
+    var tasks = [];
+
+    /**
+     * The queue of all frames. Each frame is a pairing of an array of tasks
+     * and a callback which must be called when the frame is rendered.
+     * @private
+     * @type {Frame[]}
+     */
+    var frames = [];
+
+    /**
+     * Flushes all pending frames.
+     * @private
+     */
+    function __flush_frames() {
+
+        var rendered_frames = 0;
+
+        // Draw all pending frames, if ready
+        while (rendered_frames &lt; frames.length) {
+
+            var frame = frames[rendered_frames];
+            if (!frame.isReady())
+                break;
+
+            frame.flush();
+            rendered_frames++;
+
+        } 
+
+        // Remove rendered frames from array
+        frames.splice(0, rendered_frames);
+
+    }
+
+    /**
+     * An ordered list of tasks which must be executed atomically. Once
+     * executed, an associated (and optional) callback will be called.
+     *
+     * @private
+     * @constructor
+     * @param {function} callback The function to call when this frame is
+     *                            rendered.
+     * @param {Task[]} tasks The set of tasks which must be executed to render
+     *                       this frame.
+     */
+    function Frame(callback, tasks) {
+
+        /**
+         * Returns whether this frame is ready to be rendered. This function
+         * returns true if and only if ALL underlying tasks are unblocked.
+         * 
+         * @returns {Boolean} true if all underlying tasks are unblocked,
+         *                    false otherwise.
+         */
+        this.isReady = function() {
+
+            // Search for blocked tasks
+            for (var i=0; i &lt; tasks.length; i++) {
+                if (tasks[i].blocked)
+                    return false;
+            }
+
+            // If no blocked tasks, the frame is ready
+            return true;
+
+        };
+
+        /**
+         * Renders this frame, calling the associated callback, if any, after
+         * the frame is complete. This function MUST only be called when no
+         * blocked tasks exist. Calling this function with blocked tasks
+         * will result in undefined behavior.
+         */
+        this.flush = function() {
+
+            // Draw all pending tasks.
+            for (var i=0; i &lt; tasks.length; i++)
+                tasks[i].execute();
+
+            // Call callback
+            if (callback) callback();
+
+        };
+
+    }
+
+    /**
+     * A container for an task handler. Each operation which must be ordered
+     * is associated with a Task that goes into a task queue. Tasks in this
+     * queue are executed in order once their handlers are set, while Tasks 
+     * without handlers block themselves and any following Tasks from running.
+     *
+     * @constructor
+     * @private
+     * @param {function} taskHandler The function to call when this task 
+     *                               runs, if any.
+     * @param {boolean} blocked Whether this task should start blocked.
+     */
+    function Task(taskHandler, blocked) {
+       
+        var task = this;
+       
+        /**
+         * Whether this Task is blocked.
+         * 
+         * @type {boolean}
+         */
+        this.blocked = blocked;
+
+        /**
+         * Unblocks this Task, allowing it to run.
+         */
+        this.unblock = function() {
+            if (task.blocked) {
+                task.blocked = false;
+                __flush_frames();
+            }
+        };
+
+        /**
+         * Calls the handler associated with this task IMMEDIATELY. This
+         * function does not track whether this task is marked as blocked.
+         * Enforcing the blocked status of tasks is up to the caller.
+         */
+        this.execute = function() {
+            if (taskHandler) taskHandler();
+        };
+
+    }
+
+    /**
+     * Schedules a task for future execution. The given handler will execute
+     * immediately after all previous tasks upon frame flush, unless this
+     * task is blocked. If any tasks is blocked, the entire frame will not
+     * render (and no tasks within will execute) until all tasks are unblocked.
+     * 
+     * @private
+     * @param {function} handler The function to call when possible, if any.
+     * @param {boolean} blocked Whether the task should start blocked.
+     * @returns {Task} The Task created and added to the queue for future
+     *                 running.
+     */
+    function scheduleTask(handler, blocked) {
+        var task = new Task(handler, blocked);
+        tasks.push(task);
+        return task;
+    }
+
+    /**
+     * Returns the element which contains the Guacamole display.
+     * 
+     * @return {Element} The element containing the Guacamole display.
+     */
+    this.getElement = function() {
+        return bounds;
+    };
+
+    /**
+     * Returns the width of this display.
+     * 
+     * @return {Number} The width of this display;
+     */
+    this.getWidth = function() {
+        return displayWidth;
+    };
+
+    /**
+     * Returns the height of this display.
+     * 
+     * @return {Number} The height of this display;
+     */
+    this.getHeight = function() {
+        return displayHeight;
+    };
+
+    /**
+     * Returns the default layer of this display. Each Guacamole display always
+     * has at least one layer. Other layers can optionally be created within
+     * this layer, but the default layer cannot be removed and is the absolute
+     * ancestor of all other layers.
+     * 
+     * @return {Guacamole.Display.VisibleLayer} The default layer.
+     */
+    this.getDefaultLayer = function() {
+        return default_layer;
+    };
+
+    /**
+     * Returns the cursor layer of this display. Each Guacamole display contains
+     * a layer for the image of the mouse cursor. This layer is a special case
+     * and exists above all other layers, similar to the hardware mouse cursor.
+     * 
+     * @return {Guacamole.Display.VisibleLayer} The cursor layer.
+     */
+    this.getCursorLayer = function() {
+        return cursor;
+    };
+
+    /**
+     * Creates a new layer. The new layer will be a direct child of the default
+     * layer, but can be moved to be a child of any other layer. Layers returned
+     * by this function are visible.
+     * 
+     * @return {Guacamole.Display.VisibleLayer} The newly-created layer.
+     */
+    this.createLayer = function() {
+        var layer = new Guacamole.Display.VisibleLayer(displayWidth, displayHeight);
+        layer.move(default_layer, 0, 0, 0);
+        return layer;
+    };
+
+    /**
+     * Creates a new buffer. Buffers are invisible, off-screen surfaces. They
+     * are implemented in the same manner as layers, but do not provide the
+     * same nesting semantics.
+     * 
+     * @return {Guacamole.Layer} The newly-created buffer.
+     */
+    this.createBuffer = function() {
+        var buffer = new Guacamole.Layer(0, 0);
+        buffer.autosize = 1;
+        return buffer;
+    };
+
+    /**
+     * Flush all pending draw tasks, if possible, as a new frame. If the entire
+     * frame is not ready, the flush will wait until all required tasks are
+     * unblocked.
+     * 
+     * @param {function} callback The function to call when this frame is
+     *                            flushed. This may happen immediately, or
+     *                            later when blocked tasks become unblocked.
+     */
+    this.flush = function(callback) {
+
+        // Add frame, reset tasks
+        frames.push(new Frame(callback, tasks));
+        tasks = [];
+
+        // Attempt flush
+        __flush_frames();
+
+    };
+
+    /**
+     * Sets the hotspot and image of the mouse cursor displayed within the
+     * Guacamole display.
+     * 
+     * @param {Number} hotspotX The X coordinate of the cursor hotspot.
+     * @param {Number} hotspotY The Y coordinate of the cursor hotspot.
+     * @param {Guacamole.Layer} layer The source layer containing the data which
+     *                                should be used as the mouse cursor image.
+     * @param {Number} srcx The X coordinate of the upper-left corner of the
+     *                      rectangle within the source layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcy The Y coordinate of the upper-left corner of the
+     *                      rectangle within the source layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcw The width of the rectangle within the source layer's
+     *                      coordinate space to copy data from.
+     * @param {Number} srch The height of the rectangle within the source
+     *                      layer's coordinate space to copy data from.
+
+     */
+    this.setCursor = function(hotspotX, hotspotY, layer, srcx, srcy, srcw, srch) {
+        scheduleTask(function __display_set_cursor() {
+
+            // Set hotspot
+            guac_display.cursorHotspotX = hotspotX;
+            guac_display.cursorHotspotY = hotspotY;
+
+            // Reset cursor size
+            cursor.resize(srcw, srch);
+
+            // Draw cursor to cursor layer
+            cursor.copy(layer, srcx, srcy, srcw, srch, 0, 0);
+            guac_display.moveCursor(guac_display.cursorX, guac_display.cursorY);
+
+            // Fire cursor change event
+            if (guac_display.oncursor)
+                guac_display.oncursor(cursor.toCanvas(), hotspotX, hotspotY);
+
+        });
+    };
+
+    /**
+     * Sets whether the software-rendered cursor is shown. This cursor differs
+     * from the hardware cursor in that it is built into the Guacamole.Display,
+     * and relies on its own Guacamole layer to render.
+     *
+     * @param {Boolean} [shown=true] Whether to show the software cursor.
+     */
+    this.showCursor = function(shown) {
+
+        var element = cursor.getElement();
+        var parent = element.parentNode;
+
+        // Remove from DOM if hidden
+        if (shown === false) {
+            if (parent)
+                parent.removeChild(element);
+        }
+
+        // Otherwise, ensure cursor is child of display
+        else if (parent !== display)
+            display.appendChild(element);
+
+    };
+
+    /**
+     * Sets the location of the local cursor to the given coordinates. For the
+     * sake of responsiveness, this function performs its action immediately.
+     * Cursor motion is not maintained within atomic frames.
+     * 
+     * @param {Number} x The X coordinate to move the cursor to.
+     * @param {Number} y The Y coordinate to move the cursor to.
+     */
+    this.moveCursor = function(x, y) {
+
+        // Move cursor layer
+        cursor.translate(x - guac_display.cursorHotspotX,
+                         y - guac_display.cursorHotspotY);
+
+        // Update stored position
+        guac_display.cursorX = x;
+        guac_display.cursorY = y;
+
+    };
+
+    /**
+     * Changes the size of the given Layer to the given width and height.
+     * Resizing is only attempted if the new size provided is actually different
+     * from the current size.
+     * 
+     * @param {Guacamole.Layer} layer The layer to resize.
+     * @param {Number} width The new width.
+     * @param {Number} height The new height.
+     */
+    this.resize = function(layer, width, height) {
+        scheduleTask(function __display_resize() {
+
+            layer.resize(width, height);
+
+            // Resize display if default layer is resized
+            if (layer === default_layer) {
+
+                // Update (set) display size
+                displayWidth = width;
+                displayHeight = height;
+                display.style.width = displayWidth + "px";
+                display.style.height = displayHeight + "px";
+
+                // Update bounds size
+                bounds.style.width = (displayWidth*displayScale) + "px";
+                bounds.style.height = (displayHeight*displayScale) + "px";
+
+                // Notify of resize
+                if (guac_display.onresize)
+                    guac_display.onresize(width, height);
+
+            }
+
+        });
+    };
+
+    /**
+     * Draws the specified image at the given coordinates. The image specified
+     * must already be loaded.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} x The destination X coordinate.
+     * @param {Number} y The destination Y coordinate.
+     * @param {Image} image The image to draw. Note that this is an Image
+     *                      object - not a URL.
+     */
+    this.drawImage = function(layer, x, y, image) {
+        scheduleTask(function __display_drawImage() {
+            layer.drawImage(x, y, image);
+        });
+    };
+
+    /**
+     * Draws the image contained within the specified Blob at the given
+     * coordinates. The Blob specified must already be populated with image
+     * data.
+     *
+     * @param {Guacamole.Layer} layer
+     *     The layer to draw upon.
+     *
+     * @param {Number} x
+     *     The destination X coordinate.
+     *
+     * @param {Number} y
+     *     The destination Y coordinate.
+     *
+     * @param {Blob} blob
+     *     The Blob containing the image data to draw.
+     */
+    this.drawBlob = function(layer, x, y, blob) {
+
+        // Create URL for blob
+        var url = URL.createObjectURL(blob);
+
+        // Draw and free blob URL when ready
+        var task = scheduleTask(function __display_drawBlob() {
+
+            // Draw the image only if it loaded without errors
+            if (image.width &amp;&amp; image.height)
+                layer.drawImage(x, y, image);
+
+            // Blob URL no longer needed
+            URL.revokeObjectURL(url);
+
+        }, true);
+
+        // Load image from URL
+        var image = new Image();
+        image.onload = task.unblock;
+        image.onerror = task.unblock;
+        image.src = url;
+
+    };
+
+    /**
+     * Draws the image at the specified URL at the given coordinates. The image
+     * will be loaded automatically, and this and any future operations will
+     * wait for the image to finish loading.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} x The destination X coordinate.
+     * @param {Number} y The destination Y coordinate.
+     * @param {String} url The URL of the image to draw.
+     */
+    this.draw = function(layer, x, y, url) {
+
+        var task = scheduleTask(function __display_draw() {
+
+            // Draw the image only if it loaded without errors
+            if (image.width &amp;&amp; image.height)
+                layer.drawImage(x, y, image);
+
+        }, true);
+
+        var image = new Image();
+        image.onload = task.unblock;
+        image.onerror = task.unblock;
+        image.src = url;
+
+    };
+
+    /**
+     * Plays the video at the specified URL within this layer. The video
+     * will be loaded automatically, and this and any future operations will
+     * wait for the video to finish loading. Future operations will not be
+     * executed until the video finishes playing.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {String} mimetype The mimetype of the video to play.
+     * @param {Number} duration The duration of the video in milliseconds.
+     * @param {String} url The URL of the video to play.
+     */
+    this.play = function(layer, mimetype, duration, url) {
+
+        // Start loading the video
+        var video = document.createElement("video");
+        video.type = mimetype;
+        video.src = url;
+
+        // Start copying frames when playing
+        video.addEventListener("play", function() {
+            
+            function render_callback() {
+                layer.drawImage(0, 0, video);
+                if (!video.ended)
+                    window.setTimeout(render_callback, 20);
+            }
+            
+            render_callback();
+            
+        }, false);
+
+        scheduleTask(video.play);
+
+    };
+
+    /**
+     * Transfer a rectangle of image data from one Layer to this Layer using the
+     * specified transfer function.
+     * 
+     * @param {Guacamole.Layer} srcLayer The Layer to copy image data from.
+     * @param {Number} srcx The X coordinate of the upper-left corner of the
+     *                      rectangle within the source Layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcy The Y coordinate of the upper-left corner of the
+     *                      rectangle within the source Layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcw The width of the rectangle within the source Layer's
+     *                      coordinate space to copy data from.
+     * @param {Number} srch The height of the rectangle within the source
+     *                      Layer's coordinate space to copy data from.
+     * @param {Guacamole.Layer} dstLayer The layer to draw upon.
+     * @param {Number} x The destination X coordinate.
+     * @param {Number} y The destination Y coordinate.
+     * @param {Function} transferFunction The transfer function to use to
+     *                                    transfer data from source to
+     *                                    destination.
+     */
+    this.transfer = function(srcLayer, srcx, srcy, srcw, srch, dstLayer, x, y, transferFunction) {
+        scheduleTask(function __display_transfer() {
+            dstLayer.transfer(srcLayer, srcx, srcy, srcw, srch, x, y, transferFunction);
+        });
+    };
+
+    /**
+     * Put a rectangle of image data from one Layer to this Layer directly
+     * without performing any alpha blending. Simply copy the data.
+     * 
+     * @param {Guacamole.Layer} srcLayer The Layer to copy image data from.
+     * @param {Number} srcx The X coordinate of the upper-left corner of the
+     *                      rectangle within the source Layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcy The Y coordinate of the upper-left corner of the
+     *                      rectangle within the source Layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcw The width of the rectangle within the source Layer's
+     *                      coordinate space to copy data from.
+     * @param {Number} srch The height of the rectangle within the source
+     *                      Layer's coordinate space to copy data from.
+     * @param {Guacamole.Layer} dstLayer The layer to draw upon.
+     * @param {Number} x The destination X coordinate.
+     * @param {Number} y The destination Y coordinate.
+     */
+    this.put = function(srcLayer, srcx, srcy, srcw, srch, dstLayer, x, y) {
+        scheduleTask(function __display_put() {
+            dstLayer.put(srcLayer, srcx, srcy, srcw, srch, x, y);
+        });
+    };
+
+    /**
+     * Copy a rectangle of image data from one Layer to this Layer. This
+     * operation will copy exactly the image data that will be drawn once all
+     * operations of the source Layer that were pending at the time this
+     * function was called are complete. This operation will not alter the
+     * size of the source Layer even if its autosize property is set to true.
+     * 
+     * @param {Guacamole.Layer} srcLayer The Layer to copy image data from.
+     * @param {Number} srcx The X coordinate of the upper-left corner of the
+     *                      rectangle within the source Layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcy The Y coordinate of the upper-left corner of the
+     *                      rectangle within the source Layer's coordinate
+     *                      space to copy data from.
+     * @param {Number} srcw The width of the rectangle within the source Layer's
+     *                      coordinate space to copy data from.
+     * @param {Number} srch The height of the rectangle within the source
+     *                      Layer's coordinate space to copy data from.
+     * @param {Guacamole.Layer} dstLayer The layer to draw upon.
+     * @param {Number} x The destination X coordinate.
+     * @param {Number} y The destination Y coordinate.
+     */
+    this.copy = function(srcLayer, srcx, srcy, srcw, srch, dstLayer, x, y) {
+        scheduleTask(function __display_copy() {
+            dstLayer.copy(srcLayer, srcx, srcy, srcw, srch, x, y);
+        });
+    };
+
+    /**
+     * Starts a new path at the specified point.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} x The X coordinate of the point to draw.
+     * @param {Number} y The Y coordinate of the point to draw.
+     */
+    this.moveTo = function(layer, x, y) {
+        scheduleTask(function __display_moveTo() {
+            layer.moveTo(x, y);
+        });
+    };
+
+    /**
+     * Add the specified line to the current path.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} x The X coordinate of the endpoint of the line to draw.
+     * @param {Number} y The Y coordinate of the endpoint of the line to draw.
+     */
+    this.lineTo = function(layer, x, y) {
+        scheduleTask(function __display_lineTo() {
+            layer.lineTo(x, y);
+        });
+    };
+
+    /**
+     * Add the specified arc to the current path.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} x The X coordinate of the center of the circle which
+     *                   will contain the arc.
+     * @param {Number} y The Y coordinate of the center of the circle which
+     *                   will contain the arc.
+     * @param {Number} radius The radius of the circle.
+     * @param {Number} startAngle The starting angle of the arc, in radians.
+     * @param {Number} endAngle The ending angle of the arc, in radians.
+     * @param {Boolean} negative Whether the arc should be drawn in order of
+     *                           decreasing angle.
+     */
+    this.arc = function(layer, x, y, radius, startAngle, endAngle, negative) {
+        scheduleTask(function __display_arc() {
+            layer.arc(x, y, radius, startAngle, endAngle, negative);
+        });
+    };
+
+    /**
+     * Starts a new path at the specified point.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} cp1x The X coordinate of the first control point.
+     * @param {Number} cp1y The Y coordinate of the first control point.
+     * @param {Number} cp2x The X coordinate of the second control point.
+     * @param {Number} cp2y The Y coordinate of the second control point.
+     * @param {Number} x The X coordinate of the endpoint of the curve.
+     * @param {Number} y The Y coordinate of the endpoint of the curve.
+     */
+    this.curveTo = function(layer, cp1x, cp1y, cp2x, cp2y, x, y) {
+        scheduleTask(function __display_curveTo() {
+            layer.curveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+        });
+    };
+
+    /**
+     * Closes the current path by connecting the end point with the start
+     * point (if any) with a straight line.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     */
+    this.close = function(layer) {
+        scheduleTask(function __display_close() {
+            layer.close();
+        });
+    };
+
+    /**
+     * Add the specified rectangle to the current path.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} x The X coordinate of the upper-left corner of the
+     *                   rectangle to draw.
+     * @param {Number} y The Y coordinate of the upper-left corner of the
+     *                   rectangle to draw.
+     * @param {Number} w The width of the rectangle to draw.
+     * @param {Number} h The height of the rectangle to draw.
+     */
+    this.rect = function(layer, x, y, w, h) {
+        scheduleTask(function __display_rect() {
+            layer.rect(x, y, w, h);
+        });
+    };
+
+    /**
+     * Clip all future drawing operations by the current path. The current path
+     * is implicitly closed. The current path can continue to be reused
+     * for other operations (such as fillColor()) but a new path will be started
+     * once a path drawing operation (path() or rect()) is used.
+     * 
+     * @param {Guacamole.Layer} layer The layer to affect.
+     */
+    this.clip = function(layer) {
+        scheduleTask(function __display_clip() {
+            layer.clip();
+        });
+    };
+
+    /**
+     * Stroke the current path with the specified color. The current path
+     * is implicitly closed. The current path can continue to be reused
+     * for other operations (such as clip()) but a new path will be started
+     * once a path drawing operation (path() or rect()) is used.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {String} cap The line cap style. Can be "round", "square",
+     *                     or "butt".
+     * @param {String} join The line join style. Can be "round", "bevel",
+     *                      or "miter".
+     * @param {Number} thickness The line thickness in pixels.
+     * @param {Number} r The red component of the color to fill.
+     * @param {Number} g The green component of the color to fill.
+     * @param {Number} b The blue component of the color to fill.
+     * @param {Number} a The alpha component of the color to fill.
+     */
+    this.strokeColor = function(layer, cap, join, thickness, r, g, b, a) {
+        scheduleTask(function __display_strokeColor() {
+            layer.strokeColor(cap, join, thickness, r, g, b, a);
+        });
+    };
+
+    /**
+     * Fills the current path with the specified color. The current path
+     * is implicitly closed. The current path can continue to be reused
+     * for other operations (such as clip()) but a new path will be started
+     * once a path drawing operation (path() or rect()) is used.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Number} r The red component of the color to fill.
+     * @param {Number} g The green component of the color to fill.
+     * @param {Number} b The blue component of the color to fill.
+     * @param {Number} a The alpha component of the color to fill.
+     */
+    this.fillColor = function(layer, r, g, b, a) {
+        scheduleTask(function __display_fillColor() {
+            layer.fillColor(r, g, b, a);
+        });
+    };
+
+    /**
+     * Stroke the current path with the image within the specified layer. The
+     * image data will be tiled infinitely within the stroke. The current path
+     * is implicitly closed. The current path can continue to be reused
+     * for other operations (such as clip()) but a new path will be started
+     * once a path drawing operation (path() or rect()) is used.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {String} cap The line cap style. Can be "round", "square",
+     *                     or "butt".
+     * @param {String} join The line join style. Can be "round", "bevel",
+     *                      or "miter".
+     * @param {Number} thickness The line thickness in pixels.
+     * @param {Guacamole.Layer} srcLayer The layer to use as a repeating pattern
+     *                                   within the stroke.
+     */
+    this.strokeLayer = function(layer, cap, join, thickness, srcLayer) {
+        scheduleTask(function __display_strokeLayer() {
+            layer.strokeLayer(cap, join, thickness, srcLayer);
+        });
+    };
+
+    /**
+     * Fills the current path with the image within the specified layer. The
+     * image data will be tiled infinitely within the stroke. The current path
+     * is implicitly closed. The current path can continue to be reused
+     * for other operations (such as clip()) but a new path will be started
+     * once a path drawing operation (path() or rect()) is used.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     * @param {Guacamole.Layer} srcLayer The layer to use as a repeating pattern
+     *                                   within the fill.
+     */
+    this.fillLayer = function(layer, srcLayer) {
+        scheduleTask(function __display_fillLayer() {
+            layer.fillLayer(srcLayer);
+        });
+    };
+
+    /**
+     * Push current layer state onto stack.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     */
+    this.push = function(layer) {
+        scheduleTask(function __display_push() {
+            layer.push();
+        });
+    };
+
+    /**
+     * Pop layer state off stack.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     */
+    this.pop = function(layer) {
+        scheduleTask(function __display_pop() {
+            layer.pop();
+        });
+    };
+
+    /**
+     * Reset the layer, clearing the stack, the current path, and any transform
+     * matrix.
+     * 
+     * @param {Guacamole.Layer} layer The layer to draw upon.
+     */
+    this.reset = function(layer) {
+        scheduleTask(function __display_reset() {
+            layer.reset();
+        });
+    };
+
+    /**
+     * Sets the given affine transform (defined with six values from the
+     * transform's matrix).
+     * 
+     * @param {Guacamole.Layer} layer The layer to modify.
+     * @param {Number} a The first value in the affine transform's matrix.
+     * @param {Number} b The second value in the affine transform's matrix.
+     * @param {Number} c The third value in the affine transform's matrix.
+     * @param {Number} d The fourth value in the affine transform's matrix.
+     * @param {Number} e The fifth value in the affine transform's matrix.
+     * @param {Number} f The sixth value in the affine transform's matrix.
+     */
+    this.setTransform = function(layer, a, b, c, d, e, f) {
+        scheduleTask(function __display_setTransform() {
+            layer.setTransform(a, b, c, d, e, f);
+        });
+    };
+
+    /**
+     * Applies the given affine transform (defined with six values from the
+     * transform's matrix).
+     * 
+     * @param {Guacamole.Layer} layer The layer to modify.
+     * @param {Number} a The first value in the affine transform's matrix.
+     * @param {Number} b The second value in the affine transform's matrix.
+     * @param {Number} c The third value in the affine transform's matrix.
+     * @param {Number} d The fourth value in the affine transform's matrix.
+     * @param {Number} e The fifth value in the affine transform's matrix.
+     * @param {Number} f The sixth value in the affine transform's matrix.
+     */
+    this.transform = function(layer, a, b, c, d, e, f) {
+        scheduleTask(function __display_transform() {
+            layer.transform(a, b, c, d, e, f);
+        });
+    };
+
+    /**
+     * Sets the channel mask for future operations on this Layer.
+     * 
+     * The channel mask is a Guacamole-specific compositing operation identifier
+     * with a single bit representing each of four channels (in order): source
+     * image where destination transparent, source where destination opaque,
+     * destination where source transparent, and destination where source
+     * opaque.
+     * 
+     * @param {Guacamole.Layer} layer The layer to modify.
+     * @param {Number} mask The channel mask for future operations on this
+     *                      Layer.
+     */
+    this.setChannelMask = function(layer, mask) {
+        scheduleTask(function __display_setChannelMask() {
+            layer.setChannelMask(mask);
+        });
+    };
+
+    /**
+     * Sets the miter limit for stroke operations using the miter join. This
+     * limit is the maximum ratio of the size of the miter join to the stroke
+     * width. If this ratio is exceeded, the miter will not be drawn for that
+     * joint of the path.
+     * 
+     * @param {Guacamole.Layer} layer The layer to modify.
+     * @param {Number} limit The miter limit for stroke operations using the
+     *                       miter join.
+     */
+    this.setMiterLimit = function(layer, limit) {
+        scheduleTask(function __display_setMiterLimit() {
+            layer.setMiterLimit(limit);
+        });
+    };
+
+    /**
+     * Removes the given layer container entirely, such that it is no longer
+     * contained within its parent layer, if any.
+     *
+     * @param {Guacamole.Display.VisibleLayer} layer
+     *     The layer being removed from its parent.
+     */
+    this.dispose = function dispose(layer) {
+        scheduleTask(function disposeLayer() {
+            layer.dispose();
+        });
+    };
+
+    /**
+     * Applies the given affine transform (defined with six values from the
+     * transform's matrix) to the given layer.
+     *
+     * @param {Guacamole.Display.VisibleLayer} layer
+     *     The layer being distorted.
+     *
+     * @param {Number} a
+     *     The first value in the affine transform's matrix.
+     *
+     * @param {Number} b
+     *     The second value in the affine transform's matrix.
+     *
+     * @param {Number} c
+     *     The third value in the affine transform's matrix.
+     *
+     * @param {Number} d
+     *     The fourth value in the affine transform's matrix.
+     *
+     * @param {Number} e
+     *     The fifth value in the affine transform's matrix.
+     *
+     * @param {Number} f
+     *     The sixth value in the affine transform's matrix.
+     */
+    this.distort = function distort(layer, a, b, c, d, e, f) {
+        scheduleTask(function distortLayer() {
+            layer.distort(a, b, c, d, e, f);
+        });
+    };
+
+    /**
+     * Moves the upper-left corner of the given layer to the given X and Y
+     * coordinate, sets the Z stacking order, and reparents the layer
+     * to the given parent layer.
+     *
+     * @param {Guacamole.Display.VisibleLayer} layer
+     *     The layer being moved.
+     *
+     * @param {Guacamole.Display.VisibleLayer} parent
+     *     The parent to set.
+     *
+     * @param {Number} x
+     *     The X coordinate to move to.
+     *
+     * @param {Number} y
+     *     The Y coordinate to move to.
+     *
+     * @param {Number} z
+     *     The Z coordinate to move to.
+     */
+    this.move = function move(layer, parent, x, y, z) {
+        scheduleTask(function moveLayer() {
+            layer.move(parent, x, y, z);
+        });
+    };
+
+    /**
+     * Sets the opacity of the given layer to the given value, where 255 is
+     * fully opaque and 0 is fully transparent.
+     *
+     * @param {Guacamole.Display.VisibleLayer} layer
+     *     The layer whose opacity should be set.
+     *
+     * @param {Number} alpha
+     *     The opacity to set.
+     */
+    this.shade = function shade(layer, alpha) {
+        scheduleTask(function shadeLayer() {
+            layer.shade(alpha);
+        });
+    };
+
+    /**
+     * Sets the scale of the client display element such that it renders at
+     * a relatively smaller or larger size, without affecting the true
+     * resolution of the display.
+     *
+     * @param {Number} scale The scale to resize to, where 1.0 is normal
+     *                       size (1:1 scale).
+     */
+    this.scale = function(scale) {
+
+        display.style.transform =
+        display.style.WebkitTransform =
+        display.style.MozTransform =
+        display.style.OTransform =
+        display.style.msTransform =
+
+            "scale(" + scale + "," + scale + ")";
+
+        displayScale = scale;
+
+        // Update bounds size
+        bounds.style.width = (displayWidth*displayScale) + "px";
+        bounds.style.height = (displayHeight*displayScale) + "px";
+
+    };
+
+    /**
+     * Returns the scale of the display.
+     *
+     * @return {Number} The scale of the display.
+     */
+    this.getScale = function() {
+        return displayScale;
+    };
+
+    /**
+     * Returns a canvas element containing the entire display, with all child
+     * layers composited within.
+     *
+     * @return {HTMLCanvasElement} A new canvas element containing a copy of
+     *                             the display.
+     */
+    this.flatten = function() {
+       
+        // Get destination canvas
+        var canvas = document.createElement("canvas");
+        canvas.width = default_layer.width;
+        canvas.height = default_layer.height;
+
+        var context = canvas.getContext("2d");
+
+        // Returns sorted array of children
+        function get_children(layer) {
+
+            // Build array of children
+            var children = [];
+            for (var index in layer.children)
+                children.push(layer.children[index]);
+
+            // Sort
+            children.sort(function children_comparator(a, b) {
+
+                // Compare based on Z order
+                var diff = a.z - b.z;
+                if (diff !== 0)
+                    return diff;
+
+                // If Z order identical, use document order
+                var a_element = a.getElement();
+                var b_element = b.getElement();
+                var position = b_element.compareDocumentPosition(a_element);
+
+                if (position &amp; Node.DOCUMENT_POSITION_PRECEDING) return -1;
+                if (position &amp; Node.DOCUMENT_POSITION_FOLLOWING) return  1;
+
+                // Otherwise, assume same
+                return 0;
+
+            });
+
+            // Done
+            return children;
+
+        }
+
+        // Draws the contents of the given layer at the given coordinates
+        function draw_layer(layer, x, y) {
+
+            // Draw layer
+            if (layer.width > 0 &amp;&amp; layer.height > 0) {
+
+                // Save and update alpha
+                var initial_alpha = context.globalAlpha;
+                context.globalAlpha *= layer.alpha / 255.0;
+
+                // Copy data
+                context.drawImage(layer.getCanvas(), x, y);
+
+                // Draw all children
+                var children = get_children(layer);
+                for (var i=0; i&lt;children.length; i++) {
+                    var child = children[i];
+                    draw_layer(child, x + child.x, y + child.y);
+                }
+
+                // Restore alpha
+                context.globalAlpha = initial_alpha;
+
+            }
+
+        }
+
+        // Draw default layer and all children
+        draw_layer(default_layer, 0, 0);
+
+        // Return new canvas copy
+        return canvas;
+        
+    };
+
+};
+
+/**
+ * Simple container for Guacamole.Layer, allowing layers to be easily
+ * repositioned and nested. This allows certain operations to be accelerated
+ * through DOM manipulation, rather than raster operations.
+ * 
+ * @constructor
+ * @augments Guacamole.Layer
+ * @param {Number} width The width of the Layer, in pixels. The canvas element
+ *                       backing this Layer will be given this width.
+ * @param {Number} height The height of the Layer, in pixels. The canvas element
+ *                        backing this Layer will be given this height.
+ */
+Guacamole.Display.VisibleLayer = function(width, height) {
+
+    Guacamole.Layer.apply(this, [width, height]);
+
+    /**
+     * Reference to this layer.
+     * @private
+     */
+    var layer = this;
+
+    /**
+     * Identifier which uniquely identifies this layer. This is COMPLETELY
+     * UNRELATED to the index of the underlying layer, which is specific
+     * to the Guacamole protocol, and not relevant at this level.
+     * 
+     * @private
+     * @type {Number}
+     */
+    this.__unique_id = Guacamole.Display.VisibleLayer.__next_id++;
+
+    /**
+     * The opacity of the layer container, where 255 is fully opaque and 0 is
+     * fully transparent.
+     */
+    this.alpha = 0xFF;
+
+    /**
+     * X coordinate of the upper-left corner of this layer container within
+     * its parent, in pixels.
+     * @type {Number}
+     */
+    this.x = 0;
+
+    /**
+     * Y coordinate of the upper-left corner of this layer container within
+     * its parent, in pixels.
+     * @type {Number}
+     */
+    this.y = 0;
+
+    /**
+     * Z stacking order of this layer relative to other sibling layers.
+     * @type {Number}
+     */
+    this.z = 0;
+
+    /**
+     * The affine transformation applied to this layer container. Each element
+     * corresponds to a value from the transformation matrix, with the first
+     * three values being the first row, and the last three values being the
+     * second row. There are six values total.
+     * 
+     * @type {Number[]}
+     */
+    this.matrix = [1, 0, 0, 1, 0, 0];
+
+    /**
+     * The parent layer container of this layer, if any.
+     * @type {Guacamole.Display.VisibleLayer}
+     */
+    this.parent = null;
+
+    /**
+     * Set of all children of this layer, indexed by layer index. This object
+     * will have one property per child.
+     */
+    this.children = {};
+
+    // Set layer position
+    var canvas = layer.getCanvas();
+    canvas.style.position = "absolute";
+    canvas.style.left = "0px";
+    canvas.style.top = "0px";
+
+    // Create div with given size
+    var div = document.createElement("div");
+    div.appendChild(canvas);
+    div.style.width = width + "px";
+    div.style.height = height + "px";
+    div.style.position = "absolute";
+    div.style.left = "0px";
+    div.style.top = "0px";
+    div.style.overflow = "hidden";
+
+    /**
+     * Superclass resize() function.
+     * @private
+     */
+    var __super_resize = this.resize;
+
+    this.resize = function(width, height) {
+
+        // Resize containing div
+        div.style.width = width + "px";
+        div.style.height = height + "px";
+
+        __super_resize(width, height);
+
+    };
+  
+    /**
+     * Returns the element containing the canvas and any other elements
+     * associated with this layer.
+     * @returns {Element} The element containing this layer's canvas.
+     */
+    this.getElement = function() {
+        return div;
+    };
+
+    /**
+     * The translation component of this layer's transform.
+     * @private
+     */
+    var translate = "translate(0px, 0px)"; // (0, 0)
+
+    /**
+     * The arbitrary matrix component of this layer's transform.
+     * @private
+     */
+    var matrix = "matrix(1, 0, 0, 1, 0, 0)"; // Identity
+
+    /**
+     * Moves the upper-left corner of this layer to the given X and Y
+     * coordinate.
+     * 
+     * @param {Number} x The X coordinate to move to.
+     * @param {Number} y The Y coordinate to move to.
+     */
+    this.translate = function(x, y) {
+
+        layer.x = x;
+        layer.y = y;
+
+        // Generate translation
+        translate = "translate("
+                        + x + "px,"
+                        + y + "px)";
+
+        // Set layer transform 
+        div.style.transform =
+        div.style.WebkitTransform =
+        div.style.MozTransform =
+        div.style.OTransform =
+        div.style.msTransform =
+
+            translate + " " + matrix;
+
+    };
+
+    /**
+     * Moves the upper-left corner of this VisibleLayer to the given X and Y
+     * coordinate, sets the Z stacking order, and reparents this VisibleLayer
+     * to the given VisibleLayer.
+     * 
+     * @param {Guacamole.Display.VisibleLayer} parent The parent to set.
+     * @param {Number} x The X coordinate to move to.
+     * @param {Number} y The Y coordinate to move to.
+     * @param {Number} z The Z coordinate to move to.
+     */
+    this.move = function(parent, x, y, z) {
+
+        // Set parent if necessary
+        if (layer.parent !== parent) {
+
+            // Maintain relationship
+            if (layer.parent)
+                delete layer.parent.children[layer.__unique_id];
+            layer.parent = parent;
+            parent.children[layer.__unique_id] = layer;
+
+            // Reparent element
+            var parent_element = parent.getElement();
+            parent_element.appendChild(div);
+
+        }
+
+        // Set location
+        layer.translate(x, y);
+        layer.z = z;
+        div.style.zIndex = z;
+
+    };
+
+    /**
+     * Sets the opacity of this layer to the given value, where 255 is fully
+     * opaque and 0 is fully transparent.
+     * 
+     * @param {Number} a The opacity to set.
+     */
+    this.shade = function(a) {
+        layer.alpha = a;
+        div.style.opacity = a/255.0;
+    };
+
+    /**
+     * Removes this layer container entirely, such that it is no longer
+     * contained within its parent layer, if any.
+     */
+    this.dispose = function() {
+
+        // Remove from parent container
+        if (layer.parent) {
+            delete layer.parent.children[layer.__unique_id];
+            layer.parent = null;
+        }
+
+        // Remove from parent element
+        if (div.parentNode)
+            div.parentNode.removeChild(div);
+        
+    };
+
+    /**
+     * Applies the given affine transform (defined with six values from the
+     * transform's matrix).
+     * 
+     * @param {Number} a The first value in the affine transform's matrix.
+     * @param {Number} b The second value in the affine transform's matrix.
+     * @param {Number} c The third value in the affine transform's matrix.
+     * @param {Number} d The fourth value in the affine transform's matrix.
+     * @param {Number} e The fifth value in the affine transform's matrix.
+     * @param {Number} f The sixth value in the affine transform's matrix.
+     */
+    this.distort = function(a, b, c, d, e, f) {
+
+        // Store matrix
+        layer.matrix = [a, b, c, d, e, f];
+
+        // Generate matrix transformation
+        matrix =
+
+            /* a c e
+             * b d f
+             * 0 0 1
+             */
+    
+            "matrix(" + a + "," + b + "," + c + "," + d + "," + e + "," + f + ")";
+
+        // Set layer transform 
+        div.style.transform =
+        div.style.WebkitTransform =
+        div.style.MozTransform =
+        div.style.OTransform =
+        div.style.msTransform =
+
+            translate + " " + matrix;
+
+    };
+
+};
+
+/**
+ * The next identifier to be assigned to the layer container. This identifier
+ * uniquely identifies each VisibleLayer, but is unrelated to the index of
+ * the layer, which exists at the protocol/client level only.
+ * 
+ * @private
+ * @type {Number}
+ */
+Guacamole.Display.VisibleLayer.__next_id = 0;
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
diff --git a/content/doc/1.1.0/guacamole-common-js/Guacamole.ArrayBufferReader.html b/content/doc/1.1.0/guacamole-common-js/Guacamole.ArrayBufferReader.html
new file mode 100644
index 0000000..1cdf113
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Guacamole.ArrayBufferReader.html
@@ -0,0 +1,456 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Class: ArrayBufferReader</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Class: ArrayBufferReader</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2><span class="attribs"><span class="type-signature"></span></span>
+            <span class="ancestors"><a href="Guacamole.html">Guacamole</a>.</span>ArrayBufferReader<span class="signature">(stream)</span><span class="type-signature"></span></h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+
+    
+
+    
+    <h4 class="name" id="ArrayBufferReader"><span class="type-signature"></span>new ArrayBufferReader<span class="signature">(stream)</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    A reader which automatically handles the given input stream, returning
+strictly received packets as array buffers. Note that this object will
+overwrite any installed event handlers on the given Guacamole.InputStream.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>stream</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a href="Guacamole.InputStream.html">Guacamole.InputStream</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The stream that data will be read
+                                      from.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferReader.js.html">ArrayBufferReader.js</a>, <a href="ArrayBufferReader.js.html#line31">line 31</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Events</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="event:ondata">ondata</h4>
+    
+
+    
+
+
+
+<div class="description">
+    Fired once for every blob of data received.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>buffer</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">ArrayBuffer</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The data packet received.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferReader.js.html">ArrayBufferReader.js</a>, <a href="ArrayBufferReader.js.html#line68">line 68</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="event:onend">onend</h4>
+    
+
+    
+
+
+
+<div class="description">
+    Fired once this stream is finished and no further data will be written.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferReader.js.html">ArrayBufferReader.js</a>, <a href="ArrayBufferReader.js.html#line74">line 74</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+    
+</article>
+
+</section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/doc/1.1.0/guacamole-common-js/Guacamole.ArrayBufferWriter.html b/content/doc/1.1.0/guacamole-common-js/Guacamole.ArrayBufferWriter.html
new file mode 100644
index 0000000..5c2a3a5
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Guacamole.ArrayBufferWriter.html
@@ -0,0 +1,758 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Class: ArrayBufferWriter</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Class: ArrayBufferWriter</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2><span class="attribs"><span class="type-signature"></span></span>
+            <span class="ancestors"><a href="Guacamole.html">Guacamole</a>.</span>ArrayBufferWriter<span class="signature">(stream)</span><span class="type-signature"></span></h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+
+    
+
+    
+    <h4 class="name" id="ArrayBufferWriter"><span class="type-signature"></span>new ArrayBufferWriter<span class="signature">(stream)</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    A writer which automatically writes to the given output stream with arbitrary
+binary data, supplied as ArrayBuffers.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>stream</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a href="Guacamole.OutputStream.html">Guacamole.OutputStream</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The stream that data will be written
+                                       to.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferWriter.js.html">ArrayBufferWriter.js</a>, <a href="ArrayBufferWriter.js.html#line30">line 30</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Members</h3>
+
+        
+            
+<h4 class="name" id=".DEFAULT_BLOB_LENGTH"><span class="type-signature">(static, constant) </span>DEFAULT_BLOB_LENGTH<span class="type-signature"> :Number</span></h4>
+
+
+
+
+<div class="description">
+    The default maximum blob length for new Guacamole.ArrayBufferWriter
+instances.
+</div>
+
+
+
+    <h5>Type:</h5>
+    <ul>
+        <li>
+            
+<span class="param-type">Number</span>
+
+
+        </li>
+    </ul>
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferWriter.js.html">ArrayBufferWriter.js</a>, <a href="ArrayBufferWriter.js.html#line123">line 123</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+        
+            
+<h4 class="name" id="blobLength"><span class="type-signature"></span>blobLength<span class="type-signature"> :Number</span></h4>
+
+
+
+
+<div class="description">
+    The maximum length of any blob sent by this Guacamole.ArrayBufferWriter,
+in bytes. Data sent via
+<a href="Guacamole.ArrayBufferWriter.html#sendData">sendData()</a> which exceeds
+this length will be split into multiple blobs. As the Guacamole protocol
+limits the maximum size of any instruction or instruction element to
+8192 bytes, and the contents of blobs will be base64-encoded, this value
+should only be increased with extreme caution.
+</div>
+
+
+
+    <h5>Type:</h5>
+    <ul>
+        <li>
+            
+<span class="param-type">Number</span>
+
+
+        </li>
+    </ul>
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-default">Default Value:</dt>
+    <dd class="tag-default"><ul class="dummy">
+            <li><a href="Guacamole.ArrayBufferWriter.html#.DEFAULT_BLOB_LENGTH">Guacamole.ArrayBufferWriter.DEFAULT_BLOB_LENGTH</a></li>
+        </ul></dd>
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferWriter.js.html">ArrayBufferWriter.js</a>, <a href="ArrayBufferWriter.js.html#line76">line 76</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+        
+    
+
+    
+        <h3 class="subsection-title">Methods</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="sendData"><span class="type-signature"></span>sendData<span class="signature">(data)</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Sends the given data.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>data</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">ArrayBuffer</span>
+|
+
+<span class="param-type">TypedArray</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The data to send.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferWriter.js.html">ArrayBufferWriter.js</a>, <a href="ArrayBufferWriter.js.html#line83">line 83</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="sendEnd"><span class="type-signature"></span>sendEnd<span class="signature">()</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Signals that no further text will be sent, effectively closing the
+stream.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferWriter.js.html">ArrayBufferWriter.js</a>, <a href="ArrayBufferWriter.js.html#line103">line 103</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+    
+
+    
+
+    
+        <h3 class="subsection-title">Events</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="event:onack">onack</h4>
+    
+
+    
+
+
+
+<div class="description">
+    Fired for received data, if acknowledged by the server.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>status</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a href="Guacamole.Status.html">Guacamole.Status</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The status of the operation.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="ArrayBufferWriter.js.html">ArrayBufferWriter.js</a>, <a href="ArrayBufferWriter.js.html#line112">line 112</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+    
+</article>
+
+</section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioContextFactory.html b/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioContextFactory.html
new file mode 100644
index 0000000..6596baa
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioContextFactory.html
@@ -0,0 +1,341 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Namespace: AudioContextFactory</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Namespace: AudioContextFactory</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2>
+            <span class="ancestors"><a href="Guacamole.html">Guacamole</a>.</span>AudioContextFactory</h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+            <div class="description">Maintains a singleton instance of the Web Audio API AudioContext class,
+instantiating the AudioContext only in response to the first call to
+getAudioContext(), and only if no existing AudioContext instance has been
+provided via the singleton property. Subsequent calls to getAudioContext()
+will return the same instance.</div>
+        
+
+        
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioContextFactory.js.html">AudioContextFactory.js</a>, <a href="AudioContextFactory.js.html#line31">line 31</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+        
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Members</h3>
+
+        
+            
+<h4 class="name" id=".singleton"><span class="type-signature">(static) </span>singleton<span class="type-signature"> :AudioContext</span></h4>
+
+
+
+
+<div class="description">
+    A singleton instance of a Web Audio API AudioContext object, or null if
+no instance has yes been created. This property may be manually set if
+you wish to supply your own AudioContext instance, but care must be
+taken to do so as early as possible. Assignments to this property will
+not retroactively affect the value returned by previous calls to
+getAudioContext().
+</div>
+
+
+
+    <h5>Type:</h5>
+    <ul>
+        <li>
+            
+<span class="param-type">AudioContext</span>
+
+
+        </li>
+    </ul>
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioContextFactory.js.html">AudioContextFactory.js</a>, <a href="AudioContextFactory.js.html#line43">line 43</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+        
+    
+
+    
+        <h3 class="subsection-title">Methods</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".getAudioContext"><span class="type-signature">(static) </span>getAudioContext<span class="signature">()</span><span class="type-signature"> &rarr; {AudioContext}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Returns a singleton instance of a Web Audio API AudioContext object.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioContextFactory.js.html">AudioContextFactory.js</a>, <a href="AudioContextFactory.js.html#line52">line 52</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    A singleton instance of a Web Audio API AudioContext object, or null
+    if the Web Audio API is not supported.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">AudioContext</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+    
+
+    
+
+    
+</article>
+
+</section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioPlayer.html b/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioPlayer.html
new file mode 100644
index 0000000..32bc538
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioPlayer.html
@@ -0,0 +1,734 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Class: AudioPlayer</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Class: AudioPlayer</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2><span class="attribs"><span class="type-signature"></span></span>
+            <span class="ancestors"><a href="Guacamole.html">Guacamole</a>.</span>AudioPlayer<span class="signature">()</span><span class="type-signature"></span></h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+
+    
+
+    
+    <h4 class="name" id="AudioPlayer"><span class="type-signature"></span>new AudioPlayer<span class="signature">()</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Abstract audio player which accepts, queues and plays back arbitrary audio
+data. It is up to implementations of this class to provide some means of
+handling a provided Guacamole.InputStream. Data received along the provided
+stream is to be played back immediately.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioPlayer.js.html">AudioPlayer.js</a>, <a href="AudioPlayer.js.html#line30">line 30</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Methods</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".getInstance"><span class="type-signature">(static) </span>getInstance<span class="signature">(stream, mimetype)</span><span class="type-signature"> &rarr; {<a href="Guacamole.AudioPlayer.html">Guacamole.AudioPlayer</a>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Returns an instance of Guacamole.AudioPlayer providing support for the given
+audio format. If support for the given audio format is not available, null
+is returned.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>stream</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a href="Guacamole.InputStream.html">Guacamole.InputStream</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The Guacamole.InputStream to read audio data from.</td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>mimetype</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">String</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The mimetype of the audio data in the provided stream.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioPlayer.js.html">AudioPlayer.js</a>, <a href="AudioPlayer.js.html#line97">line 97</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    A Guacamole.AudioPlayer instance supporting the given mimetype and
+    reading from the given stream, or null if support for the given mimetype
+    is absent.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type"><a href="Guacamole.AudioPlayer.html">Guacamole.AudioPlayer</a></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".getSupportedTypes"><span class="type-signature">(static) </span>getSupportedTypes<span class="signature">()</span><span class="type-signature"> &rarr; {Array.&lt;String>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Returns a list of all mimetypes supported by any built-in
+Guacamole.AudioPlayer, in rough order of priority. Beware that only the core
+mimetypes themselves will be listed. Any mimetype parameters, even required
+ones, will not be included in the list. For example, "audio/L8" is a
+supported raw audio mimetype that is supported, but it is invalid without
+additional parameters. Something like "audio/L8;rate=44100" would be valid,
+however (see https://tools.ietf.org/html/rfc4856).
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioPlayer.js.html">AudioPlayer.js</a>, <a href="AudioPlayer.js.html#line75">line 75</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    A list of all mimetypes supported by any built-in Guacamole.AudioPlayer,
+    excluding any parameters.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">Array.&lt;String></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".isSupportedType"><span class="type-signature">(static) </span>isSupportedType<span class="signature">(mimetype)</span><span class="type-signature"> &rarr; {Boolean}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Determines whether the given mimetype is supported by any built-in
+implementation of Guacamole.AudioPlayer, and thus will be properly handled
+by Guacamole.AudioPlayer.getInstance().
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>mimetype</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">String</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The mimetype to check.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioPlayer.js.html">AudioPlayer.js</a>, <a href="AudioPlayer.js.html#line56">line 56</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    true if the given mimetype is supported by any built-in
+    Guacamole.AudioPlayer, false otherwise.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">Boolean</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="sync"><span class="type-signature"></span>sync<span class="signature">()</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Notifies this Guacamole.AudioPlayer that all audio up to the current
+point in time has been given via the underlying stream, and that any
+difference in time between queued audio data and the current time can be
+considered latency.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioPlayer.js.html">AudioPlayer.js</a>, <a href="AudioPlayer.js.html#line38">line 38</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+    
+
+    
+
+    
+</article>
+
+</section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioRecorder.html b/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioRecorder.html
new file mode 100644
index 0000000..667c264
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Guacamole.AudioRecorder.html
@@ -0,0 +1,828 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Class: AudioRecorder</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Class: AudioRecorder</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2><span class="attribs"><span class="type-signature"></span></span>
+            <span class="ancestors"><a href="Guacamole.html">Guacamole</a>.</span>AudioRecorder<span class="signature">()</span><span class="type-signature"></span></h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+
+    
+
+    
+    <h4 class="name" id="AudioRecorder"><span class="type-signature"></span>new AudioRecorder<span class="signature">()</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Abstract audio recorder which streams arbitrary audio data to an underlying
+Guacamole.OutputStream. It is up to implementations of this class to provide
+some means of handling this Guacamole.OutputStream. Data produced by the
+recorder is to be sent along the provided stream immediately.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioRecorder.js.html">AudioRecorder.js</a>, <a href="AudioRecorder.js.html#line30">line 30</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Methods</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".getInstance"><span class="type-signature">(static) </span>getInstance<span class="signature">(stream, mimetype)</span><span class="type-signature"> &rarr; {<a href="Guacamole.AudioRecorder.html">Guacamole.AudioRecorder</a>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Returns an instance of Guacamole.AudioRecorder providing support for the
+given audio format. If support for the given audio format is not available,
+null is returned.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>stream</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a href="Guacamole.OutputStream.html">Guacamole.OutputStream</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The Guacamole.OutputStream to send audio data through.</td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>mimetype</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">String</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The mimetype of the audio data to be sent along the provided stream.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioRecorder.js.html">AudioRecorder.js</a>, <a href="AudioRecorder.js.html#line108">line 108</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    A Guacamole.AudioRecorder instance supporting the given mimetype and
+    writing to the given stream, or null if support for the given mimetype
+    is absent.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type"><a href="Guacamole.AudioRecorder.html">Guacamole.AudioRecorder</a></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".getSupportedTypes"><span class="type-signature">(static) </span>getSupportedTypes<span class="signature">()</span><span class="type-signature"> &rarr; {Array.&lt;String>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Returns a list of all mimetypes supported by any built-in
+Guacamole.AudioRecorder, in rough order of priority. Beware that only the
+core mimetypes themselves will be listed. Any mimetype parameters, even
+required ones, will not be included in the list. For example, "audio/L8" is
+a supported raw audio mimetype that is supported, but it is invalid without
+additional parameters. Something like "audio/L8;rate=44100" would be valid,
+however (see https://tools.ietf.org/html/rfc4856).
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioRecorder.js.html">AudioRecorder.js</a>, <a href="AudioRecorder.js.html#line86">line 86</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    A list of all mimetypes supported by any built-in
+    Guacamole.AudioRecorder, excluding any parameters.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">Array.&lt;String></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".isSupportedType"><span class="type-signature">(static) </span>isSupportedType<span class="signature">(mimetype)</span><span class="type-signature"> &rarr; {Boolean}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Determines whether the given mimetype is supported by any built-in
+implementation of Guacamole.AudioRecorder, and thus will be properly handled
+by Guacamole.AudioRecorder.getInstance().
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>mimetype</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">String</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The mimetype to check.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioRecorder.js.html">AudioRecorder.js</a>, <a href="AudioRecorder.js.html#line67">line 67</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    true if the given mimetype is supported by any built-in
+    Guacamole.AudioRecorder, false otherwise.
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">Boolean</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+    
+
+    
+
+    
+        <h3 class="subsection-title">Events</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="event:onclose">onclose</h4>
+    
+
+    
+
+
+
+<div class="description">
+    Callback which is invoked when the audio recording process has stopped
+and the underlying Guacamole stream has been closed normally. Audio will
+only resume recording if a new Guacamole.AudioRecorder is started. This
+Guacamole.AudioRecorder instance MAY NOT be reused.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioRecorder.js.html">AudioRecorder.js</a>, <a href="AudioRecorder.js.html#line40">line 40</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="event:onerror">onerror</h4>
+    
+
+    
+
+
+
+<div class="description">
+    Callback which is invoked when the audio recording process cannot
+continue due to an error, if it has started at all. The underlying
+Guacamole stream is automatically closed. Future attempts to record
+audio should not be made, and this Guacamole.AudioRecorder instance
+MAY NOT be reused.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="AudioRecorder.js.html">AudioRecorder.js</a>, <a href="AudioRecorder.js.html#line51">line 51</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+    
+</article>
+
+</section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.htm [...]
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Jan 26 2020 10:17:42 GMT-0800 (PST)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+        <!-- Google Analytics -->
+        <script type="text/javascript">
+          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+          ga('create', 'UA-75289145-1', 'auto');
+          ga('send', 'pageview');
+        </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/doc/1.1.0/guacamole-common-js/Guacamole.BlobReader.html b/content/doc/1.1.0/guacamole-common-js/Guacamole.BlobReader.html
new file mode 100644
index 0000000..8bff3b1
--- /dev/null
+++ b/content/doc/1.1.0/guacamole-common-js/Guacamole.BlobReader.html
@@ -0,0 +1,700 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Class: BlobReader</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Class: BlobReader</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2><span class="attribs"><span class="type-signature"></span></span>
+            <span class="ancestors"><a href="Guacamole.html">Guacamole</a>.</span>BlobReader<span class="signature">(stream, mimetype)</span><span class="type-signature"></span></h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+
+    
+
+    
+    <h4 class="name" id="BlobReader"><span class="type-signature"></span>new BlobReader<span class="signature">(stream, mimetype)</span><span class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    A reader which automatically handles the given input stream, assembling all
+received blobs into a single blob by appending them to each other in order.
+Note that this object will overwrite any installed event handlers on the
+given Guacamole.InputStream.
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>stream</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a href="Guacamole.InputStream.html">Guacamole.InputStream</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The stream that data will be read
+                                      from.</td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>mimetype</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">String</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last">The mimetype of the blob being built.</td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BlobReader.js.html">BlobReader.js</a>, <a href="BlobReader.js.html#line33">line 33</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Methods</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="getBlob"><span class="type-signature"></span>getBlob<span class="signature">()</span><span class="type-signature"> &rarr; {Blob}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    Returns the contents of this Guacamole.BlobReader as a Blob.
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BlobReader.js.html">BlobReader.js</a>, <a href="BlobReader.js.html#line110">line 110</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
... 251243 lines suppressed ...