diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/DocServer.ts | 2 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 4 | ||||
-rw-r--r-- | src/client/views/webcam/DashWebRTC.ts | 306 | ||||
-rw-r--r-- | src/client/views/webcam/DashWebRTC.tsx | 334 | ||||
-rw-r--r-- | src/client/views/webcam/DashWebRTCVideo.tsx | 339 |
5 files changed, 648 insertions, 337 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 2cec1046b..7ffb43684 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -21,7 +21,7 @@ import { Id, HandleUpdate } from '../new_fields/FieldSymbols'; */ export namespace DocServer { let _cache: { [id: string]: RefField | Promise<Opt<RefField>> } = {}; - let _socket: SocketIOClient.Socket; + export let _socket: SocketIOClient.Socket; // this client's distinct GUID created at initialization let GUID: string; // indicates whether or not a document is currently being udpated, and, if so, its id diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8b3c03866..3df1e0e9a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -46,8 +46,8 @@ import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; import { DashWebCam } from "../views/webcam/DashWebCam"; -import { DashWebRTC } from "../views/webcam/DashWebRTC"; import { PresElementBox } from "../views/presentationview/PresElementBox"; +import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -178,7 +178,7 @@ export namespace Docs { layout: { view: LinkFollowBox } }], [DocumentType.WEBCAM, { - layout: { view: DashWebRTC } + layout: { view: DashWebRTCVideo } }], [DocumentType.PRESELEMENT, { layout: { view: PresElementBox } diff --git a/src/client/views/webcam/DashWebRTC.ts b/src/client/views/webcam/DashWebRTC.ts new file mode 100644 index 000000000..4472f5ba5 --- /dev/null +++ b/src/client/views/webcam/DashWebRTC.ts @@ -0,0 +1,306 @@ +import { DocServer } from '../../DocServer'; + + + +export namespace DashWebRTC { + + + let isChannelReady = false; + let isInitiator = false; + let isStarted = false; + let localStream: MediaStream | undefined; + let pc: any; + let remoteStream: MediaStream | undefined; + let turnReady; + + let pcConfig = { + 'iceServers': [{ + 'urls': 'stun:stun.l.google.com:19302' + }] + }; + + // Set up audio and video regardless of what devices are present. + let sdpConstraints = { + offerToReceiveAudio: true, + offerToReceiveVideo: true + }; + + + let room = 'test'; + + //let socket = io.connect(); + + if (room !== '') { + DocServer._socket.emit('create or join', room); + console.log('Attempted to create or join room', room); + + } + + DocServer._socket.on('created', function (room: string) { + console.log('Created room ' + room); + isInitiator = true; + }); + + DocServer._socket.on('full', function (room: string) { + console.log('Room ' + room + ' is full'); + }); + + DocServer._socket.on('join', function (room: string) { + console.log('Another peer made a request to join room ' + room); + console.log('This peer is the initiator of room ' + room + '!'); + isChannelReady = true; + }); + + + DocServer._socket.on('joined', function (room: string) { + console.log('joined: ' + room); + isChannelReady = true; + }); + + + DocServer._socket.on('log', function (array: any) { + console.log.apply(console, array); + }); + + + function sendMessage(message: any) { + console.log('Client sending message: ', message); + DocServer._socket.emit('message', message); + } + + + // This client receives a message + DocServer._socket.on('message', function (message: any) { + console.log('Client received message:', message); + if (message === 'got user media') { + maybeStart(); + } else if (message.type === 'offer') { + if (!isInitiator && !isStarted) { + maybeStart(); + } + pc.setRemoteDescription(new RTCSessionDescription(message)); + doAnswer(); + } else if (message.type === 'answer' && isStarted) { + pc.setRemoteDescription(new RTCSessionDescription(message)); + } else if (message.type === 'candidate' && isStarted) { + var candidate = new RTCIceCandidate({ + sdpMLineIndex: message.label, + candidate: message.candidate + }); + pc.addIceCandidate(candidate); + } else if (message === 'bye' && isStarted) { + handleRemoteHangup(); + } + }); + + let localVideo: HTMLVideoElement; + let remoteVideo: HTMLVideoElement; + + export function setVideoObjects(localVideo: HTMLVideoElement, remoteVideo: HTMLVideoElement) { + localVideo = localVideo; + remoteVideo = remoteVideo; + } + + navigator.mediaDevices.getUserMedia({ + audio: false, + video: true + }) + .then(gotStream) + .catch(function (e) { + alert('getUserMedia() error: ' + e.name); + }); + + + function gotStream(stream: any) { + console.log('Adding local stream.'); + localStream = stream; + localVideo.srcObject = stream; + sendMessage('got user media'); + if (isInitiator) { + maybeStart(); + } + } + + let constraints = { + video: true, + audio: true + }; + + + //Trying this one out!!! + console.log('Getting user media with constraints', constraints); + + if (location.hostname !== 'localhost') { + requestTurn( + 'https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913' + ); + } + + + function maybeStart() { + console.log('>>>>>>> maybeStart() ', isStarted, localStream, isChannelReady); + if (!isStarted && typeof localStream !== 'undefined' && isChannelReady) { + console.log('>>>>>> creating peer connection'); + createPeerConnection(); + pc.addStream(localStream); + isStarted = true; + console.log('isInitiator', isInitiator); + if (isInitiator) { + doCall(); + } + } + } + + + //this will need to be changed to our version of hangUp + window.onbeforeunload = function () { + sendMessage('bye'); + }; + + function createPeerConnection() { + try { + pc = new RTCPeerConnection(undefined); + pc.onicecandidate = handleIceCandidate; + pc.onaddstream = handleRemoteStreamAdded; + pc.onremovestream = handleRemoteStreamRemoved; + console.log('Created RTCPeerConnnection'); + } catch (e) { + console.log('Failed to create PeerConnection, exception: ' + e.message); + alert('Cannot create RTCPeerConnection object.'); + return; + } + } + + function handleIceCandidate(event: any) { + console.log('icecandidate event: ', event); + if (event.candidate) { + sendMessage({ + type: 'candidate', + label: event.candidate.sdpMLineIndex, + id: event.candidate.sdpMid, + candidate: event.candidate.candidate + }); + } else { + console.log('End of candidates.'); + } + } + + function handleCreateOfferError(event: any) { + console.log('createOffer() error: ', event); + } + + function doCall() { + console.log('Sending offer to peer'); + pc.createOffer(setLocalAndSendMessage, handleCreateOfferError); + } + + function doAnswer() { + console.log('Sending answer to peer.'); + pc.createAnswer().then( + setLocalAndSendMessage, + onCreateSessionDescriptionError + ); + } + + function setLocalAndSendMessage(sessionDescription: any) { + pc.setLocalDescription(sessionDescription); + console.log('setLocalAndSendMessage sending message', sessionDescription); + sendMessage(sessionDescription); + } + + function onCreateSessionDescriptionError(error: any) { + console.log('Failed to create session description: ' + error.toString()); + } + + + function requestTurn(turnURL: any) { + var turnExists = false; + for (var i in pcConfig.iceServers) { + if (pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') { + turnExists = true; + turnReady = true; + break; + } + } + if (!turnExists) { + console.log('Getting TURN server from ', turnURL); + // No TURN server. Get one from computeengineondemand.appspot.com: + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status === 200) { + var turnServer = JSON.parse(xhr.responseText); + console.log('Got TURN server: ', turnServer); + pcConfig.iceServers.push({ + 'urls': 'turn:' + turnServer.username + '@' + turnServer.turn, + //'credential': turnServer.password + }); + turnReady = true; + } + }; + xhr.open('GET', turnURL, true); + xhr.send(); + } + } + + function handleRemoteStreamAdded(event: MediaStreamEvent) { + console.log('Remote stream added.'); + remoteStream = event.stream!; + remoteVideo.srcObject = remoteStream; + } + + function handleRemoteStreamRemoved(event: MediaStreamEvent) { + console.log('Remote stream removed. Event: ', event); + } + + function hangup() { + console.log('Hanging up.'); + stop(); + sendMessage('bye'); + } + + function handleRemoteHangup() { + console.log('Session terminated.'); + stop(); + isInitiator = false; + } + + function stop() { + isStarted = false; + pc.close(); + pc = null; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +}
\ No newline at end of file diff --git a/src/client/views/webcam/DashWebRTC.tsx b/src/client/views/webcam/DashWebRTC.tsx deleted file mode 100644 index 9c93fb4cf..000000000 --- a/src/client/views/webcam/DashWebRTC.tsx +++ /dev/null @@ -1,334 +0,0 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { CollectionFreeFormDocumentViewProps } from "../nodes/CollectionFreeFormDocumentView"; -import { FieldViewProps, FieldView } from "../nodes/FieldView"; -import { observable } from "mobx"; -import { DocumentDecorations } from "../DocumentDecorations"; -import { InkingControl } from "../InkingControl"; -import "../../views/nodes/WebBox.scss"; -import "./DashWebRTC.scss" -import adapter from 'webrtc-adapter'; - - - - -const mediaStreamConstraints = { - video: true, -}; - -const offerOptions = { - offerToReceiveVideo: 1, -}; - - -@observer -export class DashWebRTC extends React.Component<CollectionFreeFormDocumentViewProps & FieldViewProps> { - - @observable private localVideoEl: HTMLVideoElement | undefined; - @observable private peerVideoEl: HTMLVideoElement | undefined; - @observable private localStream: MediaStream | undefined; - @observable private startTime: any = null; - @observable private remoteStream: MediaStream | undefined; - @observable private localPeerConnection: any; - @observable private remotePeerConnection: any; - private callButton: HTMLButtonElement | undefined; - private startButton: HTMLButtonElement | undefined; - private hangupButton: HTMLButtonElement | undefined; - - - componentDidMount() { - this.callButton!.disabled = true; - this.hangupButton!.disabled = true; - // navigator.mediaDevices.getUserMedia(mediaStreamConstraints).then(this.gotLocalMediaStream).catch(this.handleLocalMediaStreamError); - this.localVideoEl!.addEventListener('loadedmetadata', this.logVideoLoaded); - this.peerVideoEl!.addEventListener('loadedmetadata', this.logVideoLoaded); - this.peerVideoEl!.addEventListener('onresize', this.logResizedVideo); - } - - - gotLocalMediaStream = (mediaStream: MediaStream) => { - this.localStream = mediaStream; - if (this.localVideoEl) { - this.localVideoEl.srcObject = mediaStream; - } - this.trace('Received local stream.'); - this.callButton!.disabled = false; - - } - - gotRemoteMediaStream = (event: MediaStreamEvent) => { - let mediaStream = event.stream; - this.peerVideoEl!.srcObject = mediaStream; - this.remoteStream = mediaStream!; - - } - - handleLocalMediaStreamError = (error: string) => { - //console.log("navigator.getUserMedia error: ", error); - this.trace(`navigator.getUserMedia error: ${error.toString()}.`); - - } - - logVideoLoaded = (event: any) => { - let video = event.target; - this.trace(`${video.id} videoWidth: ${video.videoWidth}px, ` + - `videoHeight: ${video.videoHeight}px.`); - } - - logResizedVideo = (event: any) => { - this.logVideoLoaded(event); - - if (this.startTime) { - let elapsedTime = window.performance.now() - this.startTime; - this.startTime = null; - this.trace(`Setup time: ${elapsedTime.toFixed(3)}ms.`); - } - - } - - handleConnection = (event: any) => { - let peerConnection = event.target; - let iceCandidate = event.candidate; - - if (iceCandidate) { - let newIceCandidate: RTCIceCandidate = new RTCIceCandidate(iceCandidate); - let otherPeer: any = this.getOtherPeer(peerConnection); - - otherPeer.addIceCandidate(newIceCandidate).then(() => { - this.handleConnectionSuccess(peerConnection); - }).catch((error: any) => { - this.handleConnectionFailure(peerConnection, error); - }); - - this.trace(`${this.getPeerName(peerConnection)} ICE candidate:\n` + - `${event.candidate.candidate}.`); - - } - } - - // Logs that the connection succeeded. - handleConnectionSuccess = (peerConnection: any) => { - this.trace(`${this.getPeerName(peerConnection)} addIceCandidate success.`); - } - - handleConnectionFailure = (peerConnection: any, error: any) => { - this.trace(`${this.getPeerName(peerConnection)} failed to add ICE Candidate:\n` + - `${error.toString()}.`); - } - - // Logs changes to the connection state. - handleConnectionChange = (event: any) => { - let peerConnection = event.target; - console.log('ICE state change event: ', event); - this.trace(`${this.getPeerName(peerConnection)} ICE state: ` + - `${peerConnection.iceConnectionState}.`); - } - - // Logs error when setting session description fails. - setSessionDescriptionError = (error: any) => { - this.trace(`Failed to create session description: ${error.toString()}.`); - } - - // Logs success when setting session description. - setDescriptionSuccess = (peerConnection: any, functionName: any) => { - let peerName = this.getPeerName(peerConnection); - this.trace(`${peerName} ${functionName} complete.`); - } - - - // Logs success when localDescription is set. - setLocalDescriptionSuccess = (peerConnection: any) => { - this.setDescriptionSuccess(peerConnection, 'setLocalDescription'); - } - - // Logs success when remoteDescription is set. - setRemoteDescriptionSuccess = (peerConnection: any) => { - this.setDescriptionSuccess(peerConnection, 'setRemoteDescription'); - } - - createdOffer = (description: any) => { - this.trace(`Offer from localPeerConnection:\n${description.sdp}`); - this.trace('localPeerConnection setLocalDescription start.'); - - this.localPeerConnection.setLocalDescription(description).then(() => { - this.setLocalDescriptionSuccess(this.localPeerConnection); - }).catch(this.setSessionDescriptionError); - - - this.trace('remotePeerConnection setRemoteDescription start.'); - this.remotePeerConnection.setRemoteDescription(description) - .then(() => { - this.setRemoteDescriptionSuccess(this.remotePeerConnection); - }).catch(this.setSessionDescriptionError); - - this.trace('remotePeerConnection createAnswer start.'); - this.remotePeerConnection.createAnswer() - .then(this.createdAnswer) - .catch(this.setSessionDescriptionError); - - } - - createdAnswer = (description: any) => { - this.trace(`Answer from remotePeerConnection:\n${description.sdp}.`); - - this.trace('remotePeerConnection setLocalDescription start.'); - this.remotePeerConnection.setLocalDescription(description) - .then(() => { - this.setLocalDescriptionSuccess(this.remotePeerConnection); - }).catch(this.setSessionDescriptionError); - - this.trace('localPeerConnection setRemoteDescription start.'); - this.localPeerConnection.setRemoteDescription(description) - .then(() => { - this.setRemoteDescriptionSuccess(this.localPeerConnection); - }).catch(this.setSessionDescriptionError); - } - - - startAction = () => { - this.startButton!.disabled = true; - navigator.mediaDevices.getUserMedia(mediaStreamConstraints) - .then(this.gotLocalMediaStream).catch(this.handleLocalMediaStreamError); - this.trace('Requesting local stream.'); - } - - - // Handles call button action: creates peer connection. - callAction = () => { - this.callButton!.disabled = true; - this.hangupButton!.disabled = false; - - this.trace('Starting call.'); - this.startTime = window.performance.now(); - - // Get local media stream tracks. - const videoTracks = this.localStream!.getVideoTracks(); - const audioTracks = this.localStream!.getAudioTracks(); - if (videoTracks.length > 0) { - this.trace(`Using video device: ${videoTracks[0].label}.`); - } - if (audioTracks.length > 0) { - this.trace(`Using audio device: ${audioTracks[0].label}.`); - } - - let servers: RTCConfiguration | undefined = undefined; // Allows for RTC server configuration. - - // Create peer connections and add behavior. - this.localPeerConnection = new RTCPeerConnection(servers); - this.trace('Created local peer connection object localPeerConnection.'); - - this.localPeerConnection.addEventListener('icecandidate', this.handleConnection); - this.localPeerConnection.addEventListener( - 'iceconnectionstatechange', this.handleConnectionChange); - - this.remotePeerConnection = new RTCPeerConnection(servers); - this.trace('Created remote peer connection object remotePeerConnection.'); - - this.remotePeerConnection.addEventListener('icecandidate', this.handleConnection); - this.remotePeerConnection.addEventListener( - 'iceconnectionstatechange', this.handleConnectionChange); - this.remotePeerConnection.addEventListener('addstream', this.gotRemoteMediaStream); - - // Add local stream to connection and create offer to connect. - this.localPeerConnection.addStream(this.localStream); - this.trace('Added local stream to localPeerConnection.'); - - this.trace('localPeerConnection createOffer start.'); - this.localPeerConnection.createOffer(offerOptions) - .then(this.createdOffer).catch(this.setSessionDescriptionError); - } - - - // Handles hangup action: ends up call, closes connections and resets peers. - hangupAction = () => { - this.localPeerConnection.close(); - this.remotePeerConnection.close(); - this.localPeerConnection = null; - this.remotePeerConnection = null; - this.hangupButton!.disabled = true; - this.callButton!.disabled = false; - this.trace('Ending call.'); - } - - // Gets the "other" peer connection. - getOtherPeer = (peerConnection: any) => { - return (peerConnection === this.localPeerConnection) ? - this.remotePeerConnection : this.localPeerConnection; - } - - // Gets the name of a certain peer connection. - getPeerName = (peerConnection: any) => { - return (peerConnection === this.localPeerConnection) ? - 'localPeerConnection' : 'remotePeerConnection'; - } - - // Logs an action (text) and the time when it happened on the console. - trace = (text: string) => { - text = text.trim(); - const now = (window.performance.now() / 1000).toFixed(3); - - console.log(now, text); - } - - - - - - - - - - - - - - - - public static LayoutString() { return FieldView.LayoutString(DashWebRTC); } - - - _ignore = 0; - onPreWheel = (e: React.WheelEvent) => { - this._ignore = e.timeStamp; - } - onPrePointer = (e: React.PointerEvent) => { - this._ignore = e.timeStamp; - } - onPostPointer = (e: React.PointerEvent) => { - if (this._ignore !== e.timeStamp) { - e.stopPropagation(); - } - } - onPostWheel = (e: React.WheelEvent) => { - if (this._ignore !== e.timeStamp) { - e.stopPropagation(); - } - } - - - - render() { - let content = - <div className="webcam-cont" style={{ width: "100%", height: "100%" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}> - <video id="localVideo" autoPlay playsInline ref={(e) => this.localVideoEl = e!}></video> - <video id="remoteVideo" autoPlay playsInline ref={(e) => this.peerVideoEl = e!}></video> - <button id="startButton" ref={(e) => this.startButton = e!} onClick={this.startAction}>Start</button> - <button id="callButton" ref={(e) => this.callButton = e!} onClick={this.callAction}>Call</button> - <button id="hangupButton" ref={(e) => this.hangupButton = e!} onClick={this.hangupAction}>Hang Up</button> - </div>; - - let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; - let classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : ""); - - - return ( - <> - <div className={classname} > - {content} - </div> - {!frozen ? (null) : <div className="webBox-overlay" onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} />} - </>); - } - - -}
\ No newline at end of file diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx new file mode 100644 index 000000000..db9c922fc --- /dev/null +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -0,0 +1,339 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { CollectionFreeFormDocumentViewProps } from "../nodes/CollectionFreeFormDocumentView"; +import { FieldViewProps, FieldView } from "../nodes/FieldView"; +import { observable } from "mobx"; +import { DocumentDecorations } from "../DocumentDecorations"; +import { InkingControl } from "../InkingControl"; +import "../../views/nodes/WebBox.scss"; +import "./DashWebRTC.scss"; +import adapter from 'webrtc-adapter'; +import { DashWebRTC } from "./DashWebRTC"; + + + + +const mediaStreamConstraints = { + video: true, +}; + +const offerOptions = { + offerToReceiveVideo: 1, +}; + + +@observer +export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentViewProps & FieldViewProps> { + + @observable private localVideoEl: HTMLVideoElement | undefined; + @observable private peerVideoEl: HTMLVideoElement | undefined; + @observable private localStream: MediaStream | undefined; + @observable private startTime: any = null; + @observable private remoteStream: MediaStream | undefined; + @observable private localPeerConnection: any; + @observable private remotePeerConnection: any; + private callButton: HTMLButtonElement | undefined; + private startButton: HTMLButtonElement | undefined; + private hangupButton: HTMLButtonElement | undefined; + + componentDidMount() { + DashWebRTC.setVideoObjects(this.localVideoEl!, this.peerVideoEl!); + } + + + // componentDidMount() { + // this.callButton!.disabled = true; + // this.hangupButton!.disabled = true; + // // navigator.mediaDevices.getUserMedia(mediaStreamConstraints).then(this.gotLocalMediaStream).catch(this.handleLocalMediaStreamError); + // this.localVideoEl!.addEventListener('loadedmetadata', this.logVideoLoaded); + // this.peerVideoEl!.addEventListener('loadedmetadata', this.logVideoLoaded); + // this.peerVideoEl!.addEventListener('onresize', this.logResizedVideo); + // } + + + // gotLocalMediaStream = (mediaStream: MediaStream) => { + // this.localStream = mediaStream; + // if (this.localVideoEl) { + // this.localVideoEl.srcObject = mediaStream; + // } + // this.trace('Received local stream.'); + // this.callButton!.disabled = false; + + // } + + // gotRemoteMediaStream = (event: MediaStreamEvent) => { + // let mediaStream = event.stream; + // this.peerVideoEl!.srcObject = mediaStream; + // this.remoteStream = mediaStream!; + + // } + + // handleLocalMediaStreamError = (error: string) => { + // //console.log("navigator.getUserMedia error: ", error); + // this.trace(`navigator.getUserMedia error: ${error.toString()}.`); + + // } + + // logVideoLoaded = (event: any) => { + // let video = event.target; + // this.trace(`${video.id} videoWidth: ${video.videoWidth}px, ` + + // `videoHeight: ${video.videoHeight}px.`); + // } + + // logResizedVideo = (event: any) => { + // this.logVideoLoaded(event); + + // if (this.startTime) { + // let elapsedTime = window.performance.now() - this.startTime; + // this.startTime = null; + // this.trace(`Setup time: ${elapsedTime.toFixed(3)}ms.`); + // } + + // } + + // handleConnection = (event: any) => { + // let peerConnection = event.target; + // let iceCandidate = event.candidate; + + // if (iceCandidate) { + // let newIceCandidate: RTCIceCandidate = new RTCIceCandidate(iceCandidate); + // let otherPeer: any = this.getOtherPeer(peerConnection); + + // otherPeer.addIceCandidate(newIceCandidate).then(() => { + // this.handleConnectionSuccess(peerConnection); + // }).catch((error: any) => { + // this.handleConnectionFailure(peerConnection, error); + // }); + + // this.trace(`${this.getPeerName(peerConnection)} ICE candidate:\n` + + // `${event.candidate.candidate}.`); + + // } + // } + + // // Logs that the connection succeeded. + // handleConnectionSuccess = (peerConnection: any) => { + // this.trace(`${this.getPeerName(peerConnection)} addIceCandidate success.`); + // } + + // handleConnectionFailure = (peerConnection: any, error: any) => { + // this.trace(`${this.getPeerName(peerConnection)} failed to add ICE Candidate:\n` + + // `${error.toString()}.`); + // } + + // // Logs changes to the connection state. + // handleConnectionChange = (event: any) => { + // let peerConnection = event.target; + // console.log('ICE state change event: ', event); + // this.trace(`${this.getPeerName(peerConnection)} ICE state: ` + + // `${peerConnection.iceConnectionState}.`); + // } + + // // Logs error when setting session description fails. + // setSessionDescriptionError = (error: any) => { + // this.trace(`Failed to create session description: ${error.toString()}.`); + // } + + // // Logs success when setting session description. + // setDescriptionSuccess = (peerConnection: any, functionName: any) => { + // let peerName = this.getPeerName(peerConnection); + // this.trace(`${peerName} ${functionName} complete.`); + // } + + + // // Logs success when localDescription is set. + // setLocalDescriptionSuccess = (peerConnection: any) => { + // this.setDescriptionSuccess(peerConnection, 'setLocalDescription'); + // } + + // // Logs success when remoteDescription is set. + // setRemoteDescriptionSuccess = (peerConnection: any) => { + // this.setDescriptionSuccess(peerConnection, 'setRemoteDescription'); + // } + + // createdOffer = (description: any) => { + // this.trace(`Offer from localPeerConnection:\n${description.sdp}`); + // this.trace('localPeerConnection setLocalDescription start.'); + + // this.localPeerConnection.setLocalDescription(description).then(() => { + // this.setLocalDescriptionSuccess(this.localPeerConnection); + // }).catch(this.setSessionDescriptionError); + + + // this.trace('remotePeerConnection setRemoteDescription start.'); + // this.remotePeerConnection.setRemoteDescription(description) + // .then(() => { + // this.setRemoteDescriptionSuccess(this.remotePeerConnection); + // }).catch(this.setSessionDescriptionError); + + // this.trace('remotePeerConnection createAnswer start.'); + // this.remotePeerConnection.createAnswer() + // .then(this.createdAnswer) + // .catch(this.setSessionDescriptionError); + + // } + + // createdAnswer = (description: any) => { + // this.trace(`Answer from remotePeerConnection:\n${description.sdp}.`); + + // this.trace('remotePeerConnection setLocalDescription start.'); + // this.remotePeerConnection.setLocalDescription(description) + // .then(() => { + // this.setLocalDescriptionSuccess(this.remotePeerConnection); + // }).catch(this.setSessionDescriptionError); + + // this.trace('localPeerConnection setRemoteDescription start.'); + // this.localPeerConnection.setRemoteDescription(description) + // .then(() => { + // this.setRemoteDescriptionSuccess(this.localPeerConnection); + // }).catch(this.setSessionDescriptionError); + // } + + + // startAction = () => { + // this.startButton!.disabled = true; + // navigator.mediaDevices.getUserMedia(mediaStreamConstraints) + // .then(this.gotLocalMediaStream).catch(this.handleLocalMediaStreamError); + // this.trace('Requesting local stream.'); + // } + + + // // Handles call button action: creates peer connection. + // callAction = () => { + // this.callButton!.disabled = true; + // this.hangupButton!.disabled = false; + + // this.trace('Starting call.'); + // this.startTime = window.performance.now(); + + // // Get local media stream tracks. + // const videoTracks = this.localStream!.getVideoTracks(); + // const audioTracks = this.localStream!.getAudioTracks(); + // if (videoTracks.length > 0) { + // this.trace(`Using video device: ${videoTracks[0].label}.`); + // } + // if (audioTracks.length > 0) { + // this.trace(`Using audio device: ${audioTracks[0].label}.`); + // } + + // let servers: RTCConfiguration | undefined = undefined; // Allows for RTC server configuration. + + // // Create peer connections and add behavior. + // this.localPeerConnection = new RTCPeerConnection(servers); + // this.trace('Created local peer connection object localPeerConnection.'); + + // this.localPeerConnection.addEventListener('icecandidate', this.handleConnection); + // this.localPeerConnection.addEventListener( + // 'iceconnectionstatechange', this.handleConnectionChange); + + // this.remotePeerConnection = new RTCPeerConnection(servers); + // this.trace('Created remote peer connection object remotePeerConnection.'); + + // this.remotePeerConnection.addEventListener('icecandidate', this.handleConnection); + // this.remotePeerConnection.addEventListener( + // 'iceconnectionstatechange', this.handleConnectionChange); + // this.remotePeerConnection.addEventListener('addstream', this.gotRemoteMediaStream); + + // // Add local stream to connection and create offer to connect. + // this.localPeerConnection.addStream(this.localStream); + // this.trace('Added local stream to localPeerConnection.'); + + // this.trace('localPeerConnection createOffer start.'); + // this.localPeerConnection.createOffer(offerOptions) + // .then(this.createdOffer).catch(this.setSessionDescriptionError); + // } + + + // // Handles hangup action: ends up call, closes connections and resets peers. + // hangupAction = () => { + // this.localPeerConnection.close(); + // this.remotePeerConnection.close(); + // this.localPeerConnection = null; + // this.remotePeerConnection = null; + // this.hangupButton!.disabled = true; + // this.callButton!.disabled = false; + // this.trace('Ending call.'); + // } + + // // Gets the "other" peer connection. + // getOtherPeer = (peerConnection: any) => { + // return (peerConnection === this.localPeerConnection) ? + // this.remotePeerConnection : this.localPeerConnection; + // } + + // // Gets the name of a certain peer connection. + // getPeerName = (peerConnection: any) => { + // return (peerConnection === this.localPeerConnection) ? + // 'localPeerConnection' : 'remotePeerConnection'; + // } + + // // Logs an action (text) and the time when it happened on the console. + // trace = (text: string) => { + // text = text.trim(); + // const now = (window.performance.now() / 1000).toFixed(3); + + // console.log(now, text); + // } + + + + + + + + + + + + + + + + public static LayoutString() { return FieldView.LayoutString(DashWebRTCVideo); } + + + _ignore = 0; + onPreWheel = (e: React.WheelEvent) => { + this._ignore = e.timeStamp; + } + onPrePointer = (e: React.PointerEvent) => { + this._ignore = e.timeStamp; + } + onPostPointer = (e: React.PointerEvent) => { + if (this._ignore !== e.timeStamp) { + e.stopPropagation(); + } + } + onPostWheel = (e: React.WheelEvent) => { + if (this._ignore !== e.timeStamp) { + e.stopPropagation(); + } + } + + + + render() { + let content = + <div className="webcam-cont" style={{ width: "100%", height: "100%" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}> + <video id="localVideo" autoPlay playsInline ref={(e) => this.localVideoEl = e!}></video> + <video id="remoteVideo" autoPlay playsInline ref={(e) => this.peerVideoEl = e!}></video> + {/* <button id="startButton" ref={(e) => this.startButton = e!} onClick={this.startAction}>Start</button> + <button id="callButton" ref={(e) => this.callButton = e!} onClick={this.callAction}>Call</button> + <button id="hangupButton" ref={(e) => this.hangupButton = e!} onClick={this.hangupAction}>Hang Up</button> */} + </div>; + + let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; + let classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : ""); + + + return ( + <> + <div className={classname} > + {content} + </div> + {!frozen ? (null) : <div className="webBox-overlay" onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} />} + </>); + } + + +}
\ No newline at end of file |