293:6635f14613ba
Anton Shestakov <av6@dwimlabs.net>, Wed, 01 Nov 2017 00:50:57 +0800
Makefile: use file targets more, results in incremental building Less work to do when only some files get changed, but more work when building from scratch. But, multiple compilers can run in parallel.

next change 317:d7821033e3c0
previous change 134:46bc2e4d7a20

coffee/webrtc.coffee

Permissions: -rw-r--r--

Other formats: Feeds:
class Tram.WebRTCInterface
lstream: null
rstream: null
constructor: (@contact) ->
@peerJid = @contact.get('jid')
init: (@initiator, constraints) ->
if constraints.audio || constraints.video
navigator.getUserMedia(constraints, @connect, @fail)
else
@connect()
connect: (stream) =>
@call = calls.add(jid: @peerJid)
@pc = new RTCPeerConnection(iceServers: Tram.config.iceServers)
if stream?
@lstream = stream
@pc.addStream(stream)
@call.set('local/stream', stream)
@pc.onicecandidate = (event) =>
if event.candidate
@sendPayload(event.candidate, 'ice')
@pc.onaddstream = (event) =>
@rstream = event.stream
@call.set('remote/stream', event.stream)
@contact.set('callstate', 'established')
if @initiator
@sendIntent('initiate')
else
@createOffer()
onPayload: (stanza) ->
if not @call?
return
el = stanza.getElementsByTagNameNS(Tram.NS.WEBRTC, 'payload')[0]
signal = JSON.parse(el.firstChild.nodeValue)
if signal.sdp
if signal.type is 'offer'
@receiveOffer(signal)
else if signal.type is 'answer'
@receiveAnswer(signal)
else if signal.candidate
@pc.addIceCandidate(new RTCIceCandidate(signal))
sendPayload: (data, type) ->
payload = JSON.stringify(data)
msg = $msg(to: @peerJid, type: 'chat')
.c('payload', xmlns: Tram.NS.WEBRTC, type: type).t(payload)
X.conn.send(msg.tree())
sendIntent: (intent) ->
msg = $msg(to: @peerJid, type: 'chat')
.c('intent', xmlns: Tram.NS.WEBRTC).t(intent)
X.conn.send(msg.tree())
createOffer: ->
@pc.createOffer((offer) =>
@pc.setLocalDescription(offer, =>
@sendPayload(@pc.localDescription, 'offer')
, @fail)
, @fail)
receiveOffer: (offer) ->
@pc.setRemoteDescription(new RTCSessionDescription(offer), =>
@pc.createAnswer((answer) =>
@pc.setLocalDescription(answer, =>
@sendPayload(@pc.localDescription, 'answer')
, @fail)
, @fail)
, @fail)
receiveAnswer: (answer) ->
@pc.setRemoteDescription(new RTCSessionDescription(answer))
fail: =>
@disconnect()
@contact.unset('callstate')
disconnect: ->
if @call?
@call.unset('remote/stream')
@call.unset('local/stream')
calls.remove(@call)
if @rstream?
@stopStream(@rstream)
#@pc?.removeStream?(@rstream)
if @lstream?
@stopStream(@lstream)
#@pc?.removeStream?(@lstream)
if @pc?
@pc.close()
@pc = null
stopStream: (stream) ->
if stream.getAudioTracks?
for track in stream.getAudioTracks()
track.stop?()
if stream.getVideoTracks?
for track in stream.getVideoTracks()
track.stop?()
stream.stop?()