perfect negotiation 3
by jib1
JavaScript
async function peer(other, polite, width = 160, height = 120) {
// This creates all the buttons. You can skip this part
const create = (container, type) => container.appendChild(document.createElement(type));
const body = create(document.documentElement, "body");
const camera = createCheckbox("Camera"), noise = createCheckbox("Noise");
const both = polite && createCheckbox("Both noise");
function createCheckbox(textContent) {
const label = create(body, "label");
const input = Object.assign(create(label, "input"), {type: "checkbox"});
Object.assign(create(label, "text"), {textContent});
return input;
}
const div = create(body, "div");
const log = msg => div.innerHTML += `${msg}<br>`;
const signaling = window;
signaling.send = msg => other.postMessage(JSON.parse(JSON.stringify(msg)), "*");
// This is the main application logic
try {
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel("both", {negotiated: true, id: 0});
if (polite) pc.oniceconnectionstatechange = () => log(pc.iceConnectionState);
camera.onclick = () => onOff(camera, () => navigator.mediaDevices.getUserMedia({video: true}));
noise.onclick = () => onOff(noise, whiteNoise);
both.onclick = () => { dc.send(both.checked); dc.onmessage({data: both.checked}); }
dc.onmessage = ({data}) => noise.checked == JSON.parse(data) || noise.click();
const onOff = async (button, getMedia) => {
try {
if (button.checked) {
if (!button.stream) button.stream = await getMedia();
button.transceiver = pc.addTransceiver(button.stream.getTracks()[0], {streams: [button.stream]});
} else {
button.transceiver.stop();
}
} catch (e) {
log(e);
}
}
pc.ontrack = ({streams: [stream]}) => {
if (!stream.video) {
stream.video = Object.assign(create(body, "video"), {width, height, autoplay: true});
}
stream.video.srcObject = stream;
...