]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/playback-ui.js
1 /* global VNC_frame_data, VNC_frame_encoding */
3 import * as WebUtil
from '../app/webutil.js';
4 import RecordingPlayer
from './playback.js';
5 import Base64
from '../core/base64.js';
9 function message(str
) {
10 const cell
= document
.getElementById('messages');
11 cell
.textContent
+= str
+ "\n";
12 cell
.scrollTop
= cell
.scrollHeight
;
16 const fname
= WebUtil
.getQueryVar('data', null);
19 return Promise
.reject("Must specify data=FOO in query string.");
22 message("Loading " + fname
+ "...");
24 return new Promise((resolve
, reject
) => {
25 const script
= document
.createElement("script");
26 script
.onload
= resolve
;
27 script
.onerror
= reject
;
28 document
.body
.appendChild(script
);
29 script
.src
= "../recordings/" + fname
;
34 const iterations
= WebUtil
.getQueryVar('iterations', 3);
35 document
.getElementById('iterations').value
= iterations
;
37 const mode
= WebUtil
.getQueryVar('mode', 3);
38 if (mode
=== 'realtime') {
39 document
.getElementById('mode2').checked
= true;
41 document
.getElementById('mode1').checked
= true;
44 /* eslint-disable-next-line camelcase */
45 message("Loaded " + VNC_frame_data
.length
+ " frames");
47 const startButton
= document
.getElementById('startButton');
48 startButton
.disabled
= false;
49 startButton
.addEventListener('click', start
);
51 message("Converting...");
53 /* eslint-disable-next-line camelcase */
54 frames
= VNC_frame_data
;
58 /* eslint-disable camelcase */
59 if (window
.VNC_frame_encoding
) {
60 // Only present in older recordings
61 encoding
= VNC_frame_encoding
;
62 /* eslint-enable camelcase */
64 let frame
= frames
[0];
65 let start
= frame
.indexOf('{', 1) + 1;
66 if (frame
.slice(start
, start
+4) === 'UkZC') {
73 for (let i
= 0;i
< frames
.length
;i
++) {
74 let frame
= frames
[i
];
76 if (frame
=== "EOF") {
81 let dataIdx
= frame
.indexOf('{', 1) + 1;
83 let time
= parseInt(frame
.slice(1, dataIdx
- 1));
86 if (encoding
=== 'base64') {
87 u8
= Base64
.decode(frame
.slice(dataIdx
));
89 u8
= new Uint8Array(frame
.length
- dataIdx
);
90 for (let j
= 0; j
< frame
.length
- dataIdx
; j
++) {
91 u8
[j
] = frame
.charCodeAt(dataIdx
+ j
);
95 frames
[i
] = { fromClient
: frame
[0] === '}',
103 class IterationPlayer
{
104 constructor(iterations
, frames
) {
105 this._iterations
= iterations
;
107 this._iteration
= undefined;
108 this._player
= undefined;
110 this._startTime
= undefined;
112 this._frames
= frames
;
114 this._state
= 'running';
116 this.onfinish
= () => {};
117 this.oniterationfinish
= () => {};
118 this.rfbdisconnected
= () => {};
123 this._startTime
= (new Date()).getTime();
125 this._realtime
= realtime
;
127 this._nextIteration();
131 const player
= new RecordingPlayer(this._frames
, this._disconnected
.bind(this));
132 player
.onfinish
= this._iterationFinish
.bind(this);
134 if (this._state
!== 'running') { return; }
137 if (this._iteration
> this._iterations
) {
142 player
.run(this._realtime
, false);
146 const endTime
= (new Date()).getTime();
147 const totalDuration
= endTime
- this._startTime
;
149 const evt
= new CustomEvent('finish',
151 { duration
: totalDuration
,
152 iterations
: this._iterations
} } );
156 _iterationFinish(duration
) {
157 const evt
= new CustomEvent('iterationfinish',
159 { duration
: duration
,
160 number
: this._iteration
} } );
161 this.oniterationfinish(evt
);
163 this._nextIteration();
166 _disconnected(clean
, frame
) {
168 this._state
= 'failed';
171 const evt
= new CustomEvent('rfbdisconnected',
175 iteration
: this._iteration
} } );
176 this.onrfbdisconnected(evt
);
181 document
.getElementById('startButton').value
= "Running";
182 document
.getElementById('startButton').disabled
= true;
184 const iterations
= document
.getElementById('iterations').value
;
188 if (document
.getElementById('mode1').checked
) {
189 message(`Starting performance playback (fullspeed) [${iterations} iteration(s)]`);
192 message(`Starting realtime playback [${iterations} iteration(s)]`);
196 const player
= new IterationPlayer(iterations
, frames
);
197 player
.oniterationfinish
= (evt
) => {
198 message(`Iteration ${evt.detail.number} took ${evt.detail.duration}ms`);
200 player
.onrfbdisconnected
= (evt
) => {
201 if (!evt
.detail
.clean
) {
202 message(`noVNC sent disconnected during iteration ${evt.detail.iteration} frame ${evt.detail.frame}`);
205 player
.onfinish
= (evt
) => {
206 const iterTime
= parseInt(evt
.detail
.duration
/ evt
.detail
.iterations
, 10);
207 message(`${evt.detail.iterations} iterations took ${evt.detail.duration}ms (average ${iterTime}ms / iteration)`);
209 document
.getElementById('startButton').disabled
= false;
210 document
.getElementById('startButton').value
= "Start";
212 player
.start(realtime
);
215 loadFile().then(enableUI
).catch(e
=> message("Error loading recording: " + e
));