blob: 7c967442d0fb1d6fbf6c455f3b2d21aab76e0151 [file] [log] [blame]
Gilles Boccon-Gibodaba1ac02023-08-07 11:34:58 -07001<html>
2
3<head>
4 <style>
5 * {
6 font-family: sans-serif;
7 }
8 </style>
9</head>
10<body>
11 Server Port <input id="port" type="text" value="8989"></input> <button id="connectButton" onclick="connect()">Connect</button><br>
12 <div id="socketState"></div>
13 <br>
14 <div id="buttons"></div><br>
15 <hr>
16 <button onclick="onGetPlayStatusButtonClicked()">Get Play Status</button><br>
17 <div id="getPlayStatusResponseTable"></div>
18 <hr>
19 <button onclick="onGetElementAttributesButtonClicked()">Get Element Attributes</button><br>
20 <div id="getElementAttributesResponseTable"></div>
21 <hr>
22 <table>
23 <tr>
24 <b>VOLUME</b>:
25 <button onclick="onVolumeDownButtonClicked()">-</button>
26 <button onclick="onVolumeUpButtonClicked()">+</button>&nbsp;
27 <span id="volumeText"></span><br>
28 </tr>
29 <tr>
30 <td><b>PLAYBACK STATUS</b></td><td><span id="playbackStatusText"></span></td>
31 </tr>
32 <tr>
33 <td><b>POSITION</b></td><td><span id="positionText"></span></td>
34 </tr>
35 <tr>
36 <td><b>TRACK</b></td><td><span id="trackText"></span></td>
37 </tr>
38 <tr>
39 <td><b>ADDRESSED PLAYER</b></td><td><span id="addressedPlayerText"></span></td>
40 </tr>
41 <tr>
42 <td><b>UID COUNTER</b></td><td><span id="uidCounterText"></span></td>
43 </tr>
44 <tr>
45 <td><b>SUPPORTED EVENTS</b></td><td><span id="supportedEventsText"></span></td>
46 </tr>
47 <tr>
48 <td><b>PLAYER SETTINGS</b></td><td><div id="playerSettingsTable"></div></td>
49 </tr>
50 </table>
51 <script>
52 const portInput = document.getElementById("port")
53 const connectButton = document.getElementById("connectButton")
54 const socketState = document.getElementById("socketState")
55 const volumeText = document.getElementById("volumeText")
56 const positionText = document.getElementById("positionText")
57 const trackText = document.getElementById("trackText")
58 const playbackStatusText = document.getElementById("playbackStatusText")
59 const addressedPlayerText = document.getElementById("addressedPlayerText")
60 const uidCounterText = document.getElementById("uidCounterText")
61 const supportedEventsText = document.getElementById("supportedEventsText")
62 const playerSettingsTable = document.getElementById("playerSettingsTable")
63 const getPlayStatusResponseTable = document.getElementById("getPlayStatusResponseTable")
64 const getElementAttributesResponseTable = document.getElementById("getElementAttributesResponseTable")
65 let socket
66 let volume = 0
67
68 const keyNames = [
69 "SELECT",
70 "UP",
71 "DOWN",
72 "LEFT",
73 "RIGHT",
74 "RIGHT_UP",
75 "RIGHT_DOWN",
76 "LEFT_UP",
77 "LEFT_DOWN",
78 "ROOT_MENU",
79 "SETUP_MENU",
80 "CONTENTS_MENU",
81 "FAVORITE_MENU",
82 "EXIT",
83 "NUMBER_0",
84 "NUMBER_1",
85 "NUMBER_2",
86 "NUMBER_3",
87 "NUMBER_4",
88 "NUMBER_5",
89 "NUMBER_6",
90 "NUMBER_7",
91 "NUMBER_8",
92 "NUMBER_9",
93 "DOT",
94 "ENTER",
95 "CLEAR",
96 "CHANNEL_UP",
97 "CHANNEL_DOWN",
98 "PREVIOUS_CHANNEL",
99 "SOUND_SELECT",
100 "INPUT_SELECT",
101 "DISPLAY_INFORMATION",
102 "HELP",
103 "PAGE_UP",
104 "PAGE_DOWN",
105 "POWER",
106 "VOLUME_UP",
107 "VOLUME_DOWN",
108 "MUTE",
109 "PLAY",
110 "STOP",
111 "PAUSE",
112 "RECORD",
113 "REWIND",
114 "FAST_FORWARD",
115 "EJECT",
116 "FORWARD",
117 "BACKWARD",
118 "ANGLE",
119 "SUBPICTURE",
120 "F1",
121 "F2",
122 "F3",
123 "F4",
124 "F5",
125 ]
126
127 document.addEventListener('keydown', onKeyDown)
128 document.addEventListener('keyup', onKeyUp)
129
130 const buttons = document.getElementById("buttons")
131 keyNames.forEach(name => {
132 const button = document.createElement("BUTTON")
133 button.appendChild(document.createTextNode(name))
134 button.addEventListener("mousedown", event => {
135 send({type: 'send-key-down', key: name})
136 })
137 button.addEventListener("mouseup", event => {
138 send({type: 'send-key-up', key: name})
139 })
140 buttons.appendChild(button)
141 })
142
143 updateVolume(0)
144
145 function connect() {
146 socket = new WebSocket(`ws://localhost:${portInput.value}`);
147 socket.onopen = _ => {
148 socketState.innerText = 'OPEN'
149 connectButton.disabled = true
150 }
151 socket.onclose = _ => {
152 socketState.innerText = 'CLOSED'
153 connectButton.disabled = false
154 }
155 socket.onerror = (error) => {
156 socketState.innerText = 'ERROR'
157 console.log(`ERROR: ${error}`)
158 connectButton.disabled = false
159 }
160 socket.onmessage = (message) => {
161 onMessage(JSON.parse(message.data))
162 }
163 }
164
165 function send(message) {
166 if (socket && socket.readyState == WebSocket.OPEN) {
167 socket.send(JSON.stringify(message))
168 }
169 }
170
171 function hmsText(position) {
172 const h_1 = 1000 * 60 * 60
173 const h = Math.floor(position / h_1)
174 position -= h * h_1
175 const m_1 = 1000 * 60
176 const m = Math.floor(position / m_1)
177 position -= m * m_1
178 const s_1 = 1000
179 const s = Math.floor(position / s_1)
180 position -= s * s_1
181
182 return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}:${position}`
183 }
184
185 function setTableHead(table, columns) {
186 let thead = table.createTHead()
187 let row = thead.insertRow()
188 for (let column of columns) {
189 let th = document.createElement("th")
190 let text = document.createTextNode(column)
191 th.appendChild(text)
192 row.appendChild(th)
193 }
194 }
195
196 function createTable(rows) {
197 const table = document.createElement("table")
198
199 if (rows.length != 0) {
200 columns = Object.keys(rows[0])
201 setTableHead(table, columns)
202 }
203 for (let element of rows) {
204 let row = table.insertRow()
205 for (key in element) {
206 let cell = row.insertCell()
207 let text = document.createTextNode(element[key])
208 cell.appendChild(text)
209 }
210 }
211 return table
212 }
213
214 function onMessage(message) {
215 console.log(message)
216 if (message.type == "set-volume") {
217 updateVolume(message.params.volume)
218 } else if (message.type == "supported-events") {
219 supportedEventsText.innerText = JSON.stringify(message.params.events)
220 } else if (message.type == "playback-position-changed") {
221 positionText.innerText = hmsText(message.params.position)
222 } else if (message.type == "playback-status-changed") {
223 playbackStatusText.innerText = message.params.status
224 } else if (message.type == "player-settings-changed") {
225 playerSettingsTable.replaceChildren(message.params.settings)
226 } else if (message.type == "track-changed") {
227 trackText.innerText = message.params.identifier
228 } else if (message.type == "addressed-player-changed") {
229 addressedPlayerText.innerText = JSON.stringify(message.params.player)
230 } else if (message.type == "uids-changed") {
231 uidCounterText.innerText = message.params.uid_counter
232 } else if (message.type == "get-play-status-response") {
233 getPlayStatusResponseTable.replaceChildren(message.params)
234 } else if (message.type == "get-element-attributes-response") {
235 getElementAttributesResponseTable.replaceChildren(createTable(message.params))
236 }
237 }
238
239 function updateVolume(newVolume) {
240 volume = newVolume
241 volumeText.innerText = `${volume} (${Math.round(100*volume/0x7F)}%)`
242 }
243
244 function onKeyDown(event) {
245 console.log(event)
246 send({ type: 'send-key-down', key: event.key })
247 }
248
249 function onKeyUp(event) {
250 console.log(event)
251 send({ type: 'send-key-up', key: event.key })
252 }
253
254 function onVolumeUpButtonClicked() {
255 updateVolume(Math.min(volume + 5, 0x7F))
256 send({ type: 'set-volume', volume })
257 }
258
259 function onVolumeDownButtonClicked() {
260 updateVolume(Math.max(volume - 5, 0))
261 send({ type: 'set-volume', volume })
262 }
263
264 function onGetPlayStatusButtonClicked() {
265 send({ type: 'get-play-status', volume })
266 }
267
268 function onGetElementAttributesButtonClicked() {
269 send({ type: 'get-element-attributes' })
270 }
271</script>
272</body>
273
274</html>