]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/playback.js
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2012 Joel Martin
4 * Licensed under MPL 2.0 (see LICENSE.txt)
7 import RFB
from '../core/rfb.js';
8 import * as Log
from '../core/util/logging.js';
9 import Base64
from '../core/base64.js';
12 if (setImmediate
=== undefined) {
13 var _immediateIdCounter
= 1;
14 var _immediateFuncs
= {};
16 var setImmediate = function (func
) {
17 var index
= _immediateIdCounter
++;
18 _immediateFuncs
[index
] = func
;
19 window
.postMessage("noVNC immediate trigger:" + index
, "*");
23 window
.clearImmediate = function (id
) {
27 var _onMessage = function (event
) {
28 if ((typeof event
.data
!== "string") ||
29 (event
.data
.indexOf("noVNC immediate trigger:") !== 0)) {
33 var index
= event
.data
.slice("noVNC immediate trigger:".length
);
35 var callback
= _immediateFuncs
[index
];
36 if (callback
=== undefined) {
40 delete _immediateFuncs
[index
];
44 window
.addEventListener("message", _onMessage
);
47 export default function RecordingPlayer (frames
, encoding
, disconnected
) {
48 this._frames
= frames
;
49 this._encoding
= encoding
;
51 this._disconnected
= disconnected
;
53 if (this._encoding
=== undefined) {
54 let frame
= this._frames
[0];
55 let start
= frame
.indexOf('{', 1) + 1;
56 if (frame
.slice(start
).startsWith('UkZC')) {
57 this._encoding
= 'base64';
59 this._encoding
= 'binary';
63 this._rfb
= undefined;
64 this._frame_length
= this._frames
.length
;
66 this._frame_index
= 0;
67 this._start_time
= undefined;
68 this._realtime
= true;
69 this._trafficManagement
= true;
71 this._running
= false;
73 this.onfinish = function () {};
76 RecordingPlayer
.prototype = {
77 run: function (realtime
, trafficManagement
) {
78 // initialize a new RFB
79 this._rfb
= new RFB(document
.getElementById('VNC_screen'), 'wss://test');
80 this._rfb
.viewOnly
= true;
81 this._rfb
.addEventListener("disconnect",
82 this._handleDisconnect
.bind(this));
83 this._enablePlaybackMode();
85 // reset the frame index and timer
86 this._frame_index
= 0;
87 this._start_time
= (new Date()).getTime();
89 this._realtime
= realtime
;
90 this._trafficManagement
= (trafficManagement
=== undefined) ? !realtime
: trafficManagement
;
94 this._queueNextPacket();
97 // _enablePlaybackMode mocks out things not required for running playback
98 _enablePlaybackMode: function () {
99 this._rfb
._sock
.send = function (arr
) {};
100 this._rfb
._sock
.close = function () {};
101 this._rfb
._sock
.flush = function () {};
102 this._rfb
._sock
.open = function () {
104 this._eventHandlers
.open();
108 _queueNextPacket: function () {
109 if (!this._running
) { return; }
111 var frame
= this._frames
[this._frame_index
];
114 while (this._frame_index
< this._frame_length
&& frame
.charAt(0) === "}") {
116 frame
= this._frames
[this._frame_index
];
119 if (frame
=== 'EOF') {
120 Log
.Debug('Finished, found EOF');
125 if (this._frame_index
>= this._frame_length
) {
126 Log
.Debug('Finished, no more frames');
131 if (this._realtime
) {
132 let foffset
= frame
.slice(1, frame
.indexOf('{', 1));
133 let toffset
= (new Date()).getTime() - this._start_time
;
134 let delay
= foffset
- toffset
;
135 if (delay
< 1) delay
= 1;
137 setTimeout(this._doPacket
.bind(this), delay
);
139 setImmediate(this._doPacket
.bind(this));
143 _doPacket: function () {
144 // Avoid having excessive queue buildup in non-realtime mode
145 if (this._trafficManagement
&& this._rfb
._flushing
) {
147 let orig
= this._rfb
._display
.onflush
;
148 this._rfb
._display
.onflush = function () {
149 player
._rfb
._display
.onflush
= orig
;
150 player
._rfb
._onFlush();
156 const frame
= this._frames
[this._frame_index
];
157 var start
= frame
.indexOf('{', 1) + 1;
158 if (this._encoding
=== 'base64') {
159 var u8
= Base64
.decode(frame
.slice(start
));
162 var u8
= new Uint8Array(frame
.length
- start
);
163 for (let i
= 0; i
< frame
.length
- start
; i
++) {
164 u8
[i
] = frame
.charCodeAt(start
+ i
);
168 this._rfb
._sock
._recv_message({'data': u8
});
171 this._queueNextPacket();
175 if (this._rfb
._display
.pending()) {
177 this._rfb
._display
.onflush = function () {
178 if (player
._rfb
._flushing
) {
179 player
._rfb
._onFlush();
183 this._rfb
._display
.flush();
185 this._running
= false;
186 this._rfb
._sock
._eventHandlers
.close({code
: 1000, reason
: ""});
188 this.onfinish((new Date()).getTime() - this._start_time
);
192 _handleDisconnect(evt
) {
193 this._running
= false;
194 this._disconnected(evt
.detail
.clean
, this._frame_index
);