Browse Source

Working again?

master
Roderic Day 4 years ago
parent
commit
81e1a3f171
3 changed files with 61 additions and 66 deletions
  1. +55
    -8
      apps/rpc.js
  2. +5
    -56
      apps/streams.js
  3. +1
    -2
      pico.html

+ 55
- 8
apps/rpc.js View File

const connections = {} const connections = {}
const datachannels = {} const datachannels = {}
const streams = {}
const screen = {}

function setTracks({source, tracks}) {
streams[source] = streams[source] || new MediaStream()
streams[source].getTracks().forEach(t => streams[source].removeTrack(t))
tracks.forEach(track => streams[source].addTrack(track))
m.redraw()

if(source === State.username) {
reloadAllStreams()
}
}

function reloadAllStreams() {
State.online.forEach(username => {
signal({kind: 'rpc', value: {type: 'request'}, source: username})
})
}

function getOwnTracks() {
if(streams[State.username]) {
return streams[State.username].getTracks()
}
else {
return []
}
}


function createConnection(target) { function createConnection(target) {
const rpc = new RTCPeerConnection(rpcConfig) const rpc = new RTCPeerConnection(rpcConfig)
wire({kind: 'rpc', value, target}) wire({kind: 'rpc', value, target})
} }
} }
rpc.ontrack = ({track}) => {
console.log(track)
rpc.ontrack = () => {
const tracks = rpc.getReceivers().map(t => t.track)
setTracks({source: target, tracks: tracks})
} }
rpc.onconnectionstatechange = () => { rpc.onconnectionstatechange = () => {
if(rpc.connectionState === 'failed') { if(rpc.connectionState === 'failed') {


async function handlePeerInfo({source: target, value}) { async function handlePeerInfo({source: target, value}) {
const rpc = connections[target] const rpc = connections[target]

if(!rpc) { if(!rpc) {
return return
} }

const olds = rpc.getSenders().map(t => t.track)
const news = getOwnTracks()
rpc.getSenders().filter(s => !news.includes(s.track)).forEach(s => rpc.removeTrack(s))
news.filter(track => !olds.includes(track)).forEach(t => t && rpc.addTrack(t))

if(value.type === 'request') { if(value.type === 'request') {
const localOffer = await rpc.createOffer() const localOffer = await rpc.createOffer()
await rpc.setLocalDescription(localOffer) await rpc.setLocalDescription(localOffer)
} }
else if(value.type === 'answer') { else if(value.type === 'answer') {
const remoteAnswer = new RTCSessionDescription(value) const remoteAnswer = new RTCSessionDescription(value)
await rpc.setRemoteDescription(remoteAnswer)
await rpc.setRemoteDescription(remoteAnswer).catch(e => e)
} }
else if(value.type === 'candidate') { else if(value.type === 'candidate') {
const candidate = new RTCIceCandidate(value.candidate) const candidate = new RTCIceCandidate(value.candidate)
await rpc.addIceCandidate(candidate)
await rpc.addIceCandidate(candidate).catch(e => e)
} }
} }


function removeConnection(user) {
const rpc = connections[user]
if(rpc) {
delete connections[user]
function destroyConnection(username) {
if(streams[username]) {
streams[username].getTracks().forEach(t => t.stop())
delete streams[username]
}
if(datachannels[username]) {
datachannels[username].close()
delete datachannels[username]
}
if(connections[username]) {
connections[username].getReceivers().forEach(r => r.track.stop())
connections[username].close()
delete connections[username]
} }
} }


addEventListener('tracks', (e) => setTracks(e.detail.value))
addEventListener('rpc', (e) => handlePeerInfo(e.detail)) addEventListener('rpc', (e) => handlePeerInfo(e.detail))
addEventListener('join', (e) => createConnection(e.detail.value)) addEventListener('join', (e) => createConnection(e.detail.value))
addEventListener('leave', (e) => destroyConnection(e.detail.value))
addEventListener('load', () => doNotLog.add('rpc')) addEventListener('load', () => doNotLog.add('rpc'))

+ 5
- 56
apps/streams.js View File

view({attrs: {label, value}}) { view({attrs: {label, value}}) {
const onclick = () => { const onclick = () => {
StreamContainer[value] = !StreamContainer[value] StreamContainer[value] = !StreamContainer[value]
updateSelfVideo()
requestStream()
} }
const checked = StreamContainer[value] const checked = StreamContainer[value]
return m('label.styled', return m('label.styled',
] ]
} }
} }
const updateSelfVideo = async () => {
const video = document.querySelector('video.self')

video.srcObject.getTracks().forEach(track => {
track.stop()
video.srcObject.removeTrack(track)
delete track
})

const requestStream = async () => {
if(StreamContainer.videoOn || StreamContainer.audioOn) { if(StreamContainer.videoOn || StreamContainer.audioOn) {
await navigator.mediaDevices await navigator.mediaDevices
.getUserMedia(VideoConfig) .getUserMedia(VideoConfig)
.then(s => s.getTracks().forEach(t => video.srcObject.addTrack(t)))
.then(s => signal({kind: 'tracks', value: {source: State.username, tracks: s.getTracks()}}))
.catch(e => console.error(e)) .catch(e => console.error(e))
} }
video.srcObject = video.srcObject // safari

wire({kind: 'peerInfo', value: {type: 'request'}})
}
const updateOtherVideo = (target, dom) => {
dom.srcObject = new MediaStream()
let rpc = null

const stopRpc = () => {
rpc && rpc.close()
dom.srcObject.getTracks().forEach(track => {
track.stop()
dom.srcObject.removeTrack(track)
delete track
})
}

const resetRpc = () => {
stopRpc()
rpc = new RTCPeerConnection(rpcConfig)
document.querySelector('video.self').srcObject.getTracks()
.forEach(t => rpc.addTrack(t))
}
} }
const Video = { const Video = {
setUp: (username) => ({dom}) => { setUp: (username) => ({dom}) => {
dom.username = username
dom.srcObject = new MediaStream()
if(username === State.username) { if(username === State.username) {
dom.classList.add('self')
dom.muted = true dom.muted = true
updateSelfVideo()
}
else {
updateOtherVideo(username, dom)
requestStream()
} }
}, },
tearDown: (username) => ({dom}) => {
removeEventListener('peerInfo', dom.listener)

dom.srcObject.getTracks().forEach(track => {
track.stop()
dom.srcObject.removeTrack(track)
delete track
})
},
view({attrs: {username}}) { view({attrs: {username}}) {
const styleOuter = { const styleOuter = {
position: 'relative', position: 'relative',
), ),
m('video[playsinline][autoplay]', { m('video[playsinline][autoplay]', {
style: styleVideo, style: styleVideo,
srcObject: streams[username],
oncreate: this.setUp(username), oncreate: this.setUp(username),
onremove: this.tearDown(username),
}), }),
) )
}, },
) )
}, },
} }
const signalPeerStop = (username) => {
signal({kind: 'peerInfo', value: {type: 'stop'}, source: username})
}
addEventListener('pagehide', () => State.online.forEach(signalPeerStop))
addEventListener('logout', () => State.online.forEach(signalPeerStop))
addEventListener('load', () => { addEventListener('load', () => {
Headers.push([VideoConfig]) Headers.push([VideoConfig])
Apps.push([StreamContainer, {key: 'stream-container'}]) Apps.push([StreamContainer, {key: 'stream-container'}])

+ 1
- 2
pico.html View File

<!-- <script src="/libs/purify.min.js"></script> --> <!-- <script src="/libs/purify.min.js"></script> -->
<script src="/pico.js" defer></script> <script src="/pico.js" defer></script>
<script src="/apps/rpc.js"></script> <script src="/apps/rpc.js"></script>
<!-- <script src="/apps/streams.js"></script> -->
<script src="/apps/streams.js"></script>
<!-- <script src="/apps/screen.js"></script> --> <!-- <script src="/apps/screen.js"></script> -->
<!-- <script src="/apps/chat.js"></script> --> <!-- <script src="/apps/chat.js"></script> -->
<!-- <script src="/apps/volume.js"></script> --> <!-- <script src="/apps/volume.js"></script> -->
<!-- <script src="/apps/screen.js"></script> -->
</head> </head>
<style> <style>
body { body {

Loading…
Cancel
Save