First working version
This commit is contained in:
95
static/js/display.js
Normal file
95
static/js/display.js
Normal file
@ -0,0 +1,95 @@
|
||||
async function init(
|
||||
name="loled-display",
|
||||
width = window.innerWidth,
|
||||
height = window.innerHeight,
|
||||
){
|
||||
|
||||
const display = document.getElementById("display")
|
||||
const video = document.getElementById("display-video")
|
||||
const nameEl = document.getElementById("display-name")
|
||||
let peerConnection = null
|
||||
|
||||
async function setNewConnection(offer, iceCandidates){
|
||||
const connection = new RTCPeerConnection({
|
||||
iceServers: [
|
||||
{urls: ["stun:stun.nextcloud.com:443"]}
|
||||
]
|
||||
})
|
||||
|
||||
connection.addEventListener("track", (e) => {
|
||||
if(e.streams.length > 0){
|
||||
video.srcObject = e.streams[0]
|
||||
video.play()
|
||||
}
|
||||
})
|
||||
|
||||
connection.addEventListener("connectionstatechange", () => {
|
||||
if(connection.connectionState == "connected"){
|
||||
nameEl.hidden = true
|
||||
} else if(["closed", "failed", "disconnected"].indexOf(connection.connectionState)) {
|
||||
nameEl.hidden = false
|
||||
}
|
||||
})
|
||||
|
||||
connection.setRemoteDescription(new RTCSessionDescription(offer))
|
||||
for(const it of iceCandidates){
|
||||
connection.addIceCandidate(it ? new RTCIceCandidate(it) : undefined)
|
||||
}
|
||||
|
||||
const answr = await connection.createAnswer()
|
||||
connection.setLocalDescription(answr)
|
||||
await fetch("/_loled/display/put-answer", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(answr),
|
||||
headers: {"content-type": "application/json"}
|
||||
})
|
||||
console.log("New offer received")
|
||||
|
||||
if(peerConnection){
|
||||
peerConnection.close()
|
||||
}
|
||||
|
||||
peerConnection = connection
|
||||
nameEl.hidden = true
|
||||
}
|
||||
|
||||
display.style.width = width+"px"
|
||||
display.style.height = height+"px"
|
||||
display.style.setProperty("--display-width", width+"px")
|
||||
display.style.setProperty("--display-height", height+"px")
|
||||
|
||||
const [registration, registerdName] = await getRegistration(name)
|
||||
name = registerdName;
|
||||
|
||||
nameEl.hidden = false
|
||||
|
||||
registration.addEventListener("message", e => {
|
||||
const message = JSON.parse(e.data)
|
||||
if(message.type == "offer"){
|
||||
setNewConnection(message.offer, message.iceCandidates)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function getRegistration(name){
|
||||
console.info("Waiting welcome message")
|
||||
const reg = new EventSource("/_loled/display/register?name="+name)
|
||||
const registeredName = await new Promise((res, rej) => {
|
||||
reg.addEventListener("message", e => {
|
||||
const message = JSON.parse(e.data)
|
||||
if(message.type != 'welcome'){
|
||||
rej(new Error("Invalid message received"))
|
||||
}
|
||||
res(message.name)
|
||||
}, {once: true})
|
||||
})
|
||||
console.info(`display registerd with name ${registeredName}`)
|
||||
return [reg, registeredName]
|
||||
}
|
||||
|
||||
const args = new URLSearchParams(location.search);
|
||||
init(
|
||||
args.get("name"),
|
||||
parseInt(args.get("width")),
|
||||
parseInt(args.get("height"))
|
||||
)
|
48
static/js/grab-canvas.js
Normal file
48
static/js/grab-canvas.js
Normal file
@ -0,0 +1,48 @@
|
||||
(async () => {
|
||||
const globalConnnection = Symbol("grab-canvas-connection")
|
||||
|
||||
const currentScriptSrc = document.currentScript.src;
|
||||
const canvas = document.querySelector("canvas");
|
||||
|
||||
if(!canvas){
|
||||
console.error("No canvas found on this page")
|
||||
}
|
||||
|
||||
const conn = new RTCPeerConnection({
|
||||
iceServers: [
|
||||
{urls: ["stun:stun.nextcloud.com:443"]}
|
||||
]
|
||||
});
|
||||
|
||||
const iceCandidates = []
|
||||
conn.addEventListener("icecandidate", e => {
|
||||
iceCandidates.push(e.candidate)
|
||||
})
|
||||
|
||||
const allCandidatesCollected = new Promise(res =>
|
||||
conn.addEventListener("icecandidate", e => e.candidate == null && res() ))
|
||||
|
||||
const canvasStream = canvas.captureStream()
|
||||
const canvasStreamTracks = canvasStream.getVideoTracks()
|
||||
if(canvasStreamTracks.length > 0){
|
||||
conn.addTrack(canvasStreamTracks[0], canvasStream)
|
||||
}
|
||||
|
||||
const offer = await conn.createOffer();
|
||||
await conn.setLocalDescription(offer);
|
||||
|
||||
await allCandidatesCollected
|
||||
|
||||
const res = await fetch(new URL("/_loled/grab-display", currentScriptSrc), {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
offer,
|
||||
iceCandidates
|
||||
})
|
||||
})
|
||||
const response = new RTCSessionDescription(await res.json());
|
||||
conn.setRemoteDescription(response);
|
||||
|
||||
window[globalConnnection] = conn
|
||||
})()
|
Reference in New Issue
Block a user