From 77acaf0a1a40c1e0f3896697963d05fa4c542cf7 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Matt Colyer Date: Tue, 23 Jul 2013 16:27:08 -0700 Subject: [PATCH] Refactor Host Session --- .../collaboration/lib/guest-session.coffee | 2 +- .../collaboration/lib/host-session.coffee | 89 ++++++------------- .../collaboration/lib/host-view.coffee | 10 +-- .../collaboration/lib/media-connection.coffee | 46 ++++++---- 4 files changed, 56 insertions(+), 91 deletions(-) diff --git a/src/packages/collaboration/lib/guest-session.coffee b/src/packages/collaboration/lib/guest-session.coffee index 1d70b3d7c..ecd73c1b7 100644 --- a/src/packages/collaboration/lib/guest-session.coffee +++ b/src/packages/collaboration/lib/guest-session.coffee @@ -32,7 +32,7 @@ class GuestSession guest = doc.get('collaborationState.guest') host = doc.get('collaborationState.host') - @mediaConnection = new MediaConnection(guest, host) + @mediaConnection = new MediaConnection(guest, host, isHost: false) waitForStream: (callback) -> @mediaConnection.waitForStream callback diff --git a/src/packages/collaboration/lib/host-session.coffee b/src/packages/collaboration/lib/host-session.coffee index c640ed1c1..ea868b8c7 100644 --- a/src/packages/collaboration/lib/host-session.coffee +++ b/src/packages/collaboration/lib/host-session.coffee @@ -4,48 +4,23 @@ _ = require 'underscore' patrick = require 'patrick' telepath = require 'telepath' +MediaConnection = require './media-connection' sessionUtils = require './session-utils' module.exports = class HostSession _.extend @prototype, require('event-emitter') - doc: null participants: null peer: null + mediaConnection: null + doc: null sharing: false - stream: null - start: -> - return if @peer? - - mediaConnection = null - - constraints = {video: true, audio: true} - success = (stream) => - mediaConnection = new webkitRTCPeerConnection(sessionUtils.getIceServers()) - mediaConnection.onicecandidate = (event) => - return unless event.candidate? - console.log "Set Host Candidate", event.candidate - @doc.set 'collaborationState.host.candidate', event.candidate - - mediaConnection.onaddstream = ({@stream}) => - @trigger 'stream-ready', @stream - console.log('Added Guest\'s Stream', @stream) - - mediaConnection.addStream(stream) - navigator.webkitGetUserMedia constraints, success, console.error - - @peer = sessionUtils.createPeer() - @doc = site.createDocument({}) - @doc.set('windowState', atom.windowState) - patrick.snapshot project.getPath(), (error, repoSnapshot) => - if error? - console.error(error) - return - - # FIXME: There be dragons here - @doc.set 'collaborationState', + constructor: -> + @doc = site.createDocument + windowState: atom.windowState + collaborationState: guest: {description: '', candidate: '', ready: false} host: {description: '', candidate: ''} participants: [] @@ -53,64 +28,50 @@ class HostSession url: git.getConfigValue('remote.origin.url') branch: git.getShortHead() - host = @doc.get 'collaborationState.host' - guest = @doc.get 'collaborationState.guest' - guest.on 'changed', ({key, newValue}) => - switch key - when 'ready' - success = (description) => - console.log "Create Offer", description - mediaConnection.setLocalDescription(description) - host.set 'description', description + host = @doc.get('collaborationState.host') + guest = @doc.get('collaborationState.guest') + @mediaConnection = new MediaConnection(host, guest, isHost: true) - mediaConnection.createOffer success, console.error - when 'description' - guestDescription = newValue.toObject() - console.log "Received Guest description", guestDescription - sessionDescription = new RTCSessionDescription(guestDescription) - mediaConnection.setRemoteDescription(sessionDescription) - when 'candidate' - guestCandidate = new RTCIceCandidate newValue.toObject() - console.log('Host received candidate', guestCandidate) - mediaConnection.addIceCandidate(new RTCIceCandidate(guestCandidate)) - else - throw new Error("Unknown guest key '#{key}'") + @peer = sessionUtils.createPeer() + + start: -> + return if @isSharing() + + patrick.snapshot project.getPath(), (error, repoSnapshot) => + throw new Error(error) if error @participants = @doc.get('collaborationState.participants') @participants.push id: @getId() email: git.getConfigValue('user.email') + @participants.on 'changed', => @trigger 'participants-changed', @participants.toObject() - @peer.on 'open', => - @sharing = true - @trigger 'started' - - @peer.on 'close', => - @sharing = false - @trigger 'stopped' - @peer.on 'connection', (connection) => connection.on 'open', => - console.log 'sending document' + @sharing = true connection.send({repoSnapshot, doc: @doc.serialize()}) sessionUtils.connectDocument(@doc, connection) + @trigger 'started' connection.on 'close', => - console.log 'sharing session stopped' + @sharing = false @participants.each (participant, index) => if connection.peer is participant.get('id') @participants.remove(index) + @trigger 'stopped' @getId() stop: -> return unless @peer? - @peer.destroy() @peer = null + waitForStream: (callback) -> + @mediaConnection.waitForStream callback + getId: -> @peer.id diff --git a/src/packages/collaboration/lib/host-view.coffee b/src/packages/collaboration/lib/host-view.coffee index 7dcc01eed..417729da7 100644 --- a/src/packages/collaboration/lib/host-view.coffee +++ b/src/packages/collaboration/lib/host-view.coffee @@ -29,17 +29,11 @@ class HostView extends View @hostSession.on 'participants-changed', (participants) => @updateParticipants(participants) - @addStream(@hostSession.stream) - @hostSession.on 'stream-ready', (stream) => - console.log "Stream is ready", stream - @addStream(stream) + @hostSession.waitForStream (stream) => + @video[0].src = URL.createObjectURL(stream) @attach() - addStream: (stream) -> - return unless stream - @video[0].src = URL.createObjectURL(stream) - updateParticipants: (participants) -> @participants.empty() hostId = @hostSession.getId() diff --git a/src/packages/collaboration/lib/media-connection.coffee b/src/packages/collaboration/lib/media-connection.coffee index d05537b57..e73a05e79 100644 --- a/src/packages/collaboration/lib/media-connection.coffee +++ b/src/packages/collaboration/lib/media-connection.coffee @@ -6,12 +6,13 @@ module.exports = class MediaConnection _.extend @prototype, require('event-emitter') - guest: null - host: null + local: null + remote: null connection: null stream: null + isHost: null - constructor: (@guest, @host) -> + constructor: (@local, @remote, {@isHost}={}) -> constraints = {video: true, audio: true} navigator.webkitGetUserMedia constraints, @onUserMediaAvailable, @onUserMediaUnavailable @@ -27,31 +28,40 @@ class MediaConnection onUserMediaAvailable: (stream) => @connection = new webkitRTCPeerConnection(sessionUtils.getIceServers()) @connection.addStream(stream) - @host.on 'changed', @onHostSignal + @remote.on 'changed', @onRemoteSignal @connection.onicecandidate = (event) => return unless event.candidate? - @guest.set 'candidate', event.candidate + @local.set 'candidate', event.candidate @connection.onaddstream = (event) => @stream = event.stream @trigger 'stream-ready', @stream - @guest.set 'ready', true + @local.set 'ready', true unless @isHost - onHostSignal: ({key, newValue}) => + onRemoteSignal: ({key, newValue}) => switch key - when 'description' - hostDescription = newValue.toObject() - sessionDescription = new RTCSessionDescription(hostDescription) - @connection.setRemoteDescription(sessionDescription) - success = (guestDescription) => - @connection.setLocalDescription(guestDescription) - @guest.set('description', guestDescription) + when 'ready' + success = (description) => + @connection.setLocalDescription(description) + @local.set 'description', description + @connection.createOffer success, console.error + + when 'description' + remoteDescription = newValue.toObject() + sessionDescription = new RTCSessionDescription(remoteDescription) + @connection.setRemoteDescription(sessionDescription) + + if not @isHost + success = (localDescription) => + @connection.setLocalDescription(localDescription) + @local.set('description', localDescription) + @connection.createAnswer success, console.error - @connection.createAnswer success, console.error when 'candidate' - hostCandidate = new RTCIceCandidate newValue.toObject() - @connection.addIceCandidate(hostCandidate) + remoteCandidate = new RTCIceCandidate newValue.toObject() + @connection.addIceCandidate(remoteCandidate) + else - throw new Error("Unknown host key '#{key}'") + throw new Error("Unknown remote key '#{key}'")