| <html> | |
| <head> | |
| <style> | |
| * { | |
| font-family: sans-serif; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| Server Port <input id="port" type="text" value="8989"></input> <button id="connectButton" onclick="connect()">Connect</button><br> | |
| <div id="socketState"></div> | |
| <br> | |
| <div id="buttons"></div><br> | |
| <hr> | |
| <button onclick="onGetPlayStatusButtonClicked()">Get Play Status</button><br> | |
| <div id="getPlayStatusResponseTable"></div> | |
| <hr> | |
| <button onclick="onGetElementAttributesButtonClicked()">Get Element Attributes</button><br> | |
| <div id="getElementAttributesResponseTable"></div> | |
| <hr> | |
| <table> | |
| <tr> | |
| <b>VOLUME</b>: | |
| <button onclick="onVolumeDownButtonClicked()">-</button> | |
| <button onclick="onVolumeUpButtonClicked()">+</button> | |
| <span id="volumeText"></span><br> | |
| </tr> | |
| <tr> | |
| <td><b>PLAYBACK STATUS</b></td><td><span id="playbackStatusText"></span></td> | |
| </tr> | |
| <tr> | |
| <td><b>POSITION</b></td><td><span id="positionText"></span></td> | |
| </tr> | |
| <tr> | |
| <td><b>TRACK</b></td><td><span id="trackText"></span></td> | |
| </tr> | |
| <tr> | |
| <td><b>ADDRESSED PLAYER</b></td><td><span id="addressedPlayerText"></span></td> | |
| </tr> | |
| <tr> | |
| <td><b>UID COUNTER</b></td><td><span id="uidCounterText"></span></td> | |
| </tr> | |
| <tr> | |
| <td><b>SUPPORTED EVENTS</b></td><td><span id="supportedEventsText"></span></td> | |
| </tr> | |
| <tr> | |
| <td><b>PLAYER SETTINGS</b></td><td><div id="playerSettingsTable"></div></td> | |
| </tr> | |
| </table> | |
| <script> | |
| const portInput = document.getElementById("port") | |
| const connectButton = document.getElementById("connectButton") | |
| const socketState = document.getElementById("socketState") | |
| const volumeText = document.getElementById("volumeText") | |
| const positionText = document.getElementById("positionText") | |
| const trackText = document.getElementById("trackText") | |
| const playbackStatusText = document.getElementById("playbackStatusText") | |
| const addressedPlayerText = document.getElementById("addressedPlayerText") | |
| const uidCounterText = document.getElementById("uidCounterText") | |
| const supportedEventsText = document.getElementById("supportedEventsText") | |
| const playerSettingsTable = document.getElementById("playerSettingsTable") | |
| const getPlayStatusResponseTable = document.getElementById("getPlayStatusResponseTable") | |
| const getElementAttributesResponseTable = document.getElementById("getElementAttributesResponseTable") | |
| let socket | |
| let volume = 0 | |
| const keyNames = [ | |
| "SELECT", | |
| "UP", | |
| "DOWN", | |
| "LEFT", | |
| "RIGHT", | |
| "RIGHT_UP", | |
| "RIGHT_DOWN", | |
| "LEFT_UP", | |
| "LEFT_DOWN", | |
| "ROOT_MENU", | |
| "SETUP_MENU", | |
| "CONTENTS_MENU", | |
| "FAVORITE_MENU", | |
| "EXIT", | |
| "NUMBER_0", | |
| "NUMBER_1", | |
| "NUMBER_2", | |
| "NUMBER_3", | |
| "NUMBER_4", | |
| "NUMBER_5", | |
| "NUMBER_6", | |
| "NUMBER_7", | |
| "NUMBER_8", | |
| "NUMBER_9", | |
| "DOT", | |
| "ENTER", | |
| "CLEAR", | |
| "CHANNEL_UP", | |
| "CHANNEL_DOWN", | |
| "PREVIOUS_CHANNEL", | |
| "SOUND_SELECT", | |
| "INPUT_SELECT", | |
| "DISPLAY_INFORMATION", | |
| "HELP", | |
| "PAGE_UP", | |
| "PAGE_DOWN", | |
| "POWER", | |
| "VOLUME_UP", | |
| "VOLUME_DOWN", | |
| "MUTE", | |
| "PLAY", | |
| "STOP", | |
| "PAUSE", | |
| "RECORD", | |
| "REWIND", | |
| "FAST_FORWARD", | |
| "EJECT", | |
| "FORWARD", | |
| "BACKWARD", | |
| "ANGLE", | |
| "SUBPICTURE", | |
| "F1", | |
| "F2", | |
| "F3", | |
| "F4", | |
| "F5", | |
| ] | |
| document.addEventListener('keydown', onKeyDown) | |
| document.addEventListener('keyup', onKeyUp) | |
| const buttons = document.getElementById("buttons") | |
| keyNames.forEach(name => { | |
| const button = document.createElement("BUTTON") | |
| button.appendChild(document.createTextNode(name)) | |
| button.addEventListener("mousedown", event => { | |
| send({type: 'send-key-down', key: name}) | |
| }) | |
| button.addEventListener("mouseup", event => { | |
| send({type: 'send-key-up', key: name}) | |
| }) | |
| buttons.appendChild(button) | |
| }) | |
| updateVolume(0) | |
| function connect() { | |
| socket = new WebSocket(`ws://localhost:${portInput.value}`); | |
| socket.onopen = _ => { | |
| socketState.innerText = 'OPEN' | |
| connectButton.disabled = true | |
| } | |
| socket.onclose = _ => { | |
| socketState.innerText = 'CLOSED' | |
| connectButton.disabled = false | |
| } | |
| socket.onerror = (error) => { | |
| socketState.innerText = 'ERROR' | |
| console.log(`ERROR: ${error}`) | |
| connectButton.disabled = false | |
| } | |
| socket.onmessage = (message) => { | |
| onMessage(JSON.parse(message.data)) | |
| } | |
| } | |
| function send(message) { | |
| if (socket && socket.readyState == WebSocket.OPEN) { | |
| socket.send(JSON.stringify(message)) | |
| } | |
| } | |
| function hmsText(position) { | |
| const h_1 = 1000 * 60 * 60 | |
| const h = Math.floor(position / h_1) | |
| position -= h * h_1 | |
| const m_1 = 1000 * 60 | |
| const m = Math.floor(position / m_1) | |
| position -= m * m_1 | |
| const s_1 = 1000 | |
| const s = Math.floor(position / s_1) | |
| position -= s * s_1 | |
| return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}:${position}` | |
| } | |
| function setTableHead(table, columns) { | |
| let thead = table.createTHead() | |
| let row = thead.insertRow() | |
| for (let column of columns) { | |
| let th = document.createElement("th") | |
| let text = document.createTextNode(column) | |
| th.appendChild(text) | |
| row.appendChild(th) | |
| } | |
| } | |
| function createTable(rows) { | |
| const table = document.createElement("table") | |
| if (rows.length != 0) { | |
| columns = Object.keys(rows[0]) | |
| setTableHead(table, columns) | |
| } | |
| for (let element of rows) { | |
| let row = table.insertRow() | |
| for (key in element) { | |
| let cell = row.insertCell() | |
| let text = document.createTextNode(element[key]) | |
| cell.appendChild(text) | |
| } | |
| } | |
| return table | |
| } | |
| function onMessage(message) { | |
| console.log(message) | |
| if (message.type == "set-volume") { | |
| updateVolume(message.params.volume) | |
| } else if (message.type == "supported-events") { | |
| supportedEventsText.innerText = JSON.stringify(message.params.events) | |
| } else if (message.type == "playback-position-changed") { | |
| positionText.innerText = hmsText(message.params.position) | |
| } else if (message.type == "playback-status-changed") { | |
| playbackStatusText.innerText = message.params.status | |
| } else if (message.type == "player-settings-changed") { | |
| playerSettingsTable.replaceChildren(message.params.settings) | |
| } else if (message.type == "track-changed") { | |
| trackText.innerText = message.params.identifier | |
| } else if (message.type == "addressed-player-changed") { | |
| addressedPlayerText.innerText = JSON.stringify(message.params.player) | |
| } else if (message.type == "uids-changed") { | |
| uidCounterText.innerText = message.params.uid_counter | |
| } else if (message.type == "get-play-status-response") { | |
| getPlayStatusResponseTable.replaceChildren(message.params) | |
| } else if (message.type == "get-element-attributes-response") { | |
| getElementAttributesResponseTable.replaceChildren(createTable(message.params)) | |
| } | |
| } | |
| function updateVolume(newVolume) { | |
| volume = newVolume | |
| volumeText.innerText = `${volume} (${Math.round(100*volume/0x7F)}%)` | |
| } | |
| function onKeyDown(event) { | |
| console.log(event) | |
| send({ type: 'send-key-down', key: event.key }) | |
| } | |
| function onKeyUp(event) { | |
| console.log(event) | |
| send({ type: 'send-key-up', key: event.key }) | |
| } | |
| function onVolumeUpButtonClicked() { | |
| updateVolume(Math.min(volume + 5, 0x7F)) | |
| send({ type: 'set-volume', volume }) | |
| } | |
| function onVolumeDownButtonClicked() { | |
| updateVolume(Math.max(volume - 5, 0)) | |
| send({ type: 'set-volume', volume }) | |
| } | |
| function onGetPlayStatusButtonClicked() { | |
| send({ type: 'get-play-status', volume }) | |
| } | |
| function onGetElementAttributesButtonClicked() { | |
| send({ type: 'get-element-attributes' }) | |
| } | |
| </script> | |
| </body> | |
| </html> |