1<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> 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>