]>
Commit | Line | Data |
---|---|---|
8727f598 JD |
1 | /* global VNC_frame_data, VNC_frame_encoding */ |
2 | ||
d6c17390 SR |
3 | import * as WebUtil from '../app/webutil.js'; |
4 | import RecordingPlayer from './playback.js'; | |
5 | ||
2b5f94fa JD |
6 | let frames = null; |
7 | let encoding = null; | |
d6c17390 SR |
8 | |
9 | function message(str) { | |
2b5f94fa | 10 | const cell = document.getElementById('messages'); |
d6c17390 SR |
11 | cell.textContent += str + "\n"; |
12 | cell.scrollTop = cell.scrollHeight; | |
13 | } | |
14 | ||
15 | function loadFile() { | |
16 | const fname = WebUtil.getQueryVar('data', null); | |
17 | ||
18 | if (!fname) { | |
19 | return Promise.reject("Must specify data=FOO in query string."); | |
20 | } | |
21 | ||
22 | message("Loading " + fname); | |
7c1f1a9c | 23 | |
651c23ec | 24 | return new Promise((resolve, reject) => { |
2b5f94fa | 25 | const script = document.createElement("script"); |
7c1f1a9c PO |
26 | script.onload = resolve; |
27 | script.onerror = reject; | |
28 | document.body.appendChild(script); | |
29 | script.src = "../recordings/" + fname; | |
30 | }); | |
d6c17390 SR |
31 | } |
32 | ||
7c1f1a9c | 33 | function enableUI() { |
2b5f94fa | 34 | const iterations = WebUtil.getQueryVar('iterations', 3); |
d6c17390 SR |
35 | document.getElementById('iterations').value = iterations; |
36 | ||
2b5f94fa | 37 | const mode = WebUtil.getQueryVar('mode', 3); |
d6c17390 SR |
38 | if (mode === 'realtime') { |
39 | document.getElementById('mode2').checked = true; | |
40 | } else { | |
41 | document.getElementById('mode1').checked = true; | |
42 | } | |
43 | ||
7c1f1a9c | 44 | message("VNC_frame_data.length: " + VNC_frame_data.length); |
d6c17390 SR |
45 | |
46 | const startButton = document.getElementById('startButton'); | |
afb621d5 | 47 | startButton.disabled = false; |
d6c17390 SR |
48 | startButton.addEventListener('click', start); |
49 | ||
7c1f1a9c | 50 | frames = VNC_frame_data; |
b05a7b1d PO |
51 | // Only present in older recordings |
52 | if (window.VNC_frame_encoding) | |
53 | encoding = VNC_frame_encoding; | |
d6c17390 SR |
54 | } |
55 | ||
0e4808bf JD |
56 | class IterationPlayer { |
57 | constructor(iterations, frames, encoding) { | |
58 | this._iterations = iterations; | |
d6c17390 | 59 | |
0e4808bf JD |
60 | this._iteration = undefined; |
61 | this._player = undefined; | |
d6c17390 | 62 | |
0e4808bf | 63 | this._start_time = undefined; |
d6c17390 | 64 | |
0e4808bf JD |
65 | this._frames = frames; |
66 | this._encoding = encoding; | |
d6c17390 | 67 | |
0e4808bf | 68 | this._state = 'running'; |
d6c17390 | 69 | |
651c23ec JD |
70 | this.onfinish = () => {}; |
71 | this.oniterationfinish = () => {}; | |
72 | this.rfbdisconnected = () => {}; | |
0e4808bf | 73 | } |
d6c17390 | 74 | |
0e4808bf | 75 | start(mode) { |
d6c17390 SR |
76 | this._iteration = 0; |
77 | this._start_time = (new Date()).getTime(); | |
78 | ||
79 | this._realtime = mode.startsWith('realtime'); | |
80 | this._trafficMgmt = !mode.endsWith('-no-mgmt'); | |
81 | ||
82 | this._nextIteration(); | |
0e4808bf | 83 | } |
d6c17390 | 84 | |
0e4808bf | 85 | _nextIteration() { |
5b20d338 | 86 | const player = new RecordingPlayer(this._frames, this._encoding, this._disconnected.bind(this)); |
d6c17390 SR |
87 | player.onfinish = this._iterationFinish.bind(this); |
88 | ||
89 | if (this._state !== 'running') { return; } | |
90 | ||
91 | this._iteration++; | |
92 | if (this._iteration > this._iterations) { | |
93 | this._finish(); | |
94 | return; | |
95 | } | |
96 | ||
97 | player.run(this._realtime, this._trafficMgmt); | |
0e4808bf | 98 | } |
d6c17390 | 99 | |
0e4808bf | 100 | _finish() { |
d6c17390 SR |
101 | const endTime = (new Date()).getTime(); |
102 | const totalDuration = endTime - this._start_time; | |
103 | ||
104 | const evt = new Event('finish'); | |
105 | evt.duration = totalDuration; | |
106 | evt.iterations = this._iterations; | |
107 | this.onfinish(evt); | |
0e4808bf | 108 | } |
d6c17390 | 109 | |
0e4808bf | 110 | _iterationFinish(duration) { |
d6c17390 SR |
111 | const evt = new Event('iterationfinish'); |
112 | evt.duration = duration; | |
113 | evt.number = this._iteration; | |
114 | this.oniterationfinish(evt); | |
115 | ||
116 | this._nextIteration(); | |
0e4808bf | 117 | } |
d6c17390 | 118 | |
0e4808bf | 119 | _disconnected(clean, frame) { |
d472f3f1 | 120 | if (!clean) { |
d6c17390 SR |
121 | this._state = 'failed'; |
122 | } | |
123 | ||
2b5f94fa | 124 | const evt = new Event('rfbdisconnected'); |
d472f3f1 | 125 | evt.clean = clean; |
d6c17390 | 126 | evt.frame = frame; |
a92c3317 | 127 | evt.iteration = this._iteration; |
d6c17390 SR |
128 | |
129 | this.onrfbdisconnected(evt); | |
0e4808bf JD |
130 | } |
131 | } | |
d6c17390 SR |
132 | |
133 | function start() { | |
134 | document.getElementById('startButton').value = "Running"; | |
135 | document.getElementById('startButton').disabled = true; | |
136 | ||
137 | const iterations = document.getElementById('iterations').value; | |
138 | ||
2b5f94fa | 139 | let mode; |
d6c17390 SR |
140 | |
141 | if (document.getElementById('mode1').checked) { | |
142 | message(`Starting performance playback (fullspeed) [${iterations} iteration(s)]`); | |
143 | mode = 'perftest'; | |
144 | } else { | |
145 | message(`Starting realtime playback [${iterations} iteration(s)]`); | |
146 | mode = 'realtime'; | |
147 | } | |
148 | ||
149 | const player = new IterationPlayer(iterations, frames, encoding); | |
651c23ec | 150 | player.oniterationfinish = (evt) => { |
d6c17390 SR |
151 | message(`Iteration ${evt.number} took ${evt.duration}ms`); |
152 | }; | |
651c23ec | 153 | player.onrfbdisconnected = (evt) => { |
a92c3317 | 154 | if (!evt.clean) { |
d6c17390 SR |
155 | message(`noVNC sent disconnected during iteration ${evt.iteration} frame ${evt.frame}`); |
156 | } | |
157 | }; | |
651c23ec | 158 | player.onfinish = (evt) => { |
d6c17390 SR |
159 | const iterTime = parseInt(evt.duration / evt.iterations, 10); |
160 | message(`${evt.iterations} iterations took ${evt.duration}ms (average ${iterTime}ms / iteration)`); | |
161 | ||
162 | document.getElementById('startButton').disabled = false; | |
163 | document.getElementById('startButton').value = "Start"; | |
164 | }; | |
165 | player.start(mode); | |
166 | } | |
167 | ||
651c23ec | 168 | loadFile().then(enableUI).catch(e => message("Error loading recording: " + e)); |