UNPKG

5.33 kBtext/coffeescriptView Raw
1{EventEmitter} = eio
2PeerConnection = window.PeerConnection or window.webkitPeerConnection00 or window.webkitRTCPeerConnection
3IceCandidate = window.RTCIceCandidate
4SessionDescription = window.RTCSessionDescription
5URL = window.URL or window.webkitURL or window.msURL or window.oURL
6getUserMedia = navigator.getUserMedia or navigator.webkitGetUserMedia or navigator.mozGetUserMedia or navigator.msGetUserMedia
7
8class RTC extends EventEmitter
9 constructor: (opts={}) ->
10 opts.host ?= window.location.hostname
11 opts.port ?= (if window.location.port.length > 0 then parseInt window.location.port else 80)
12 opts.secure ?= (window.location.protocol is 'https:')
13 opts.path ?= "/holla"
14
15 @socket = new eio.Socket opts
16 @socket.on "open", @emit.bind "connected"
17 @socket.on "close", @emit.bind "disconnected"
18 @socket.on "error", @emit.bind "error"
19 @socket.on "message", (msg) =>
20 msg = JSON.parse msg
21 if msg.type is "presence"
22 @emit "presence", msg.args
23 @emit "presence.#{msg.args.name}", msg.args.online
24 return
25 return unless msg.type is "offer"
26 c = new Call @, msg.from, false
27 @emit "call", c
28 return
29
30 register: (name, cb) ->
31 @socket.send JSON.stringify
32 type: "register"
33 args:
34 name: name
35
36 handle = (msg) =>
37 msg = JSON.parse msg
38 return unless msg.type is "register"
39 @socket.removeListener "message", handle
40 if msg.args.result is true
41 @user = name
42 @authorized = true
43 @emit "authorized"
44 cb? msg.args.result
45 @socket.on "message", handle
46
47 call: (user) -> new Call @, user, true
48
49 ready: (fn) ->
50 if @authorized
51 fn()
52 else
53 @once 'authorized', fn
54
55class Call extends EventEmitter
56 constructor: (@parent, @user, @isCaller) ->
57 @startTime = new Date
58 @socket = @parent.socket
59
60 @pc = @createConnection()
61 if @isCaller
62 @socket.send JSON.stringify
63 type: "offer"
64 to: @user
65 @emit "calling"
66 @socket.on "message", @handleMessage
67
68 createConnection: ->
69 pc = new PeerConnection holla.config
70 pc.onconnecting = =>
71 @emit 'connecting'
72 return
73 pc.onopen = =>
74 @emit 'connected'
75 return
76 pc.onicecandidate = (evt) =>
77 if evt.candidate
78 @socket.send JSON.stringify
79 type: "candidate"
80 to: @user
81 args:
82 candidate: evt.candidate
83 return
84
85 pc.onaddstream = (evt) =>
86 @remoteStream = evt.stream
87 @_ready = true
88 @emit "ready", @remoteStream
89 return
90 pc.onremovestream = (evt) =>
91 console.log evt
92 return
93
94 return pc
95
96 handleMessage: (msg) =>
97 msg = JSON.parse msg
98 return unless msg.from is @user
99 if msg.type is "answer"
100 return @emit "rejected" unless msg.args.accepted
101 @emit "answered"
102 @initSDP()
103 else if msg.type is "candidate"
104 @pc.addIceCandidate new IceCandidate msg.args.candidate
105 else if msg.type is "sdp"
106 @pc.setRemoteDescription new SessionDescription msg.args
107 @emit "sdp"
108 else if msg.type is "hangup"
109 @emit "hangup"
110 else if msg.type is "chat"
111 @emit "chat", msg.args.message
112 return
113
114 addStream: (s) ->
115 @pc.addStream s
116 return @
117
118 ready: (fn) ->
119 if @_ready
120 fn @remoteStream
121 else
122 @once 'ready', fn
123 return @
124
125 duration: ->
126 s = @endTime.getTime() if @endTime?
127 s ?= Date.now()
128 e = @startTime.getTime()
129 return (s-e)/1000
130
131 chat: (msg) ->
132 @socket.send JSON.stringify
133 type: "chat"
134 to: @user
135 args:
136 message: msg
137 return @
138
139 answer: ->
140 @startTime = new Date
141 @socket.send JSON.stringify
142 type: "answer"
143 to: @user
144 args:
145 accepted: true
146 @initSDP()
147 return @
148
149 decline: ->
150 @socket.send JSON.stringify
151 type: "answer"
152 to: @user
153 args:
154 accepted: false
155 return @
156
157 end: ->
158 @endTime = new Date
159 @pc.close()
160 @socket.send JSON.stringify
161 type: "hangup"
162 to: @user
163 @emit "hangup"
164 return @
165
166 initSDP: ->
167 done = (desc) =>
168 @pc.setLocalDescription desc
169 @socket.send JSON.stringify
170 type: "sdp"
171 to: @user
172 args: desc
173
174 err = (e) -> console.log e
175
176 return @pc.createOffer done, err if @isCaller
177 return @pc.createAnswer done, err if @pc.remoteDescription
178 @once "sdp", =>
179 @pc.createAnswer done, err
180
181
182holla =
183 Call: Call
184 RTC: RTC
185 supported: PeerConnection? and getUserMedia?
186 connect: (host) -> new RTC host
187 config:
188 iceServers: [url: "stun:stun.l.google.com:19302"]
189
190 streamToBlob: (s) -> URL.createObjectURL s
191 pipe: (stream, el) ->
192 uri = holla.streamToBlob stream
193 if typeof el is "string"
194 document.getElementById(el).src
195 else if el.jquery
196 el.attr 'src', uri
197 else
198 el.src = uri
199 return holla
200
201 createStream: (opt, cb) ->
202 return cb "Missing getUserMedia" unless getUserMedia?
203 err = cb
204 succ = (s) -> cb null, s
205 getUserMedia.call navigator, opt, succ, err
206 return holla
207
208 createFullStream: (cb) -> holla.createStream {video:true,audio:true}, cb
209 createVideoStream: (cb) -> holla.createStream {video:true,audio:false}, cb
210 createAudioStream: (cb) -> holla.createStream {video:true,audio:false}, cb
211
212window.holla = holla
\No newline at end of file