diff options
Diffstat (limited to 'src/client/views/webcam/DashWebRTCVideo.tsx')
-rw-r--r-- | src/client/views/webcam/DashWebRTCVideo.tsx | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx new file mode 100644 index 000000000..f93d4a662 --- /dev/null +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -0,0 +1,404 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { CollectionFreeFormDocumentViewProps } from "../nodes/CollectionFreeFormDocumentView"; +import { FieldViewProps, FieldView } from "../nodes/FieldView"; +import { observable, action } from "mobx"; +import { DocumentDecorations, CloseCall } from "../DocumentDecorations"; +import { InkingControl } from "../InkingControl"; +import "../../views/nodes/WebBox.scss"; +import "./DashWebRTCVideo.scss"; +import adapter from 'webrtc-adapter'; +import { DocServer } from "../../DocServer"; +import { DocumentView } from "../nodes/DocumentView"; +import { Utils } from "../../../Utils"; +import { MessageStore } from "../../../server/Message"; +import { initialize, hangup } from "./WebCamLogic"; + +const mediaStreamConstraints = { + video: true, +}; + +const offerOptions = { + offerToReceiveVideo: 1, +}; + +/** + * This models the component that will be rendered, that can be used as a doc that will reflect the video cams. + */ +@observer +export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentViewProps & FieldViewProps> { + @observable private localVideoEl: HTMLVideoElement | undefined; + @observable private peerVideoEl: HTMLVideoElement | undefined; + private roomText: HTMLInputElement | undefined; + // private roomOfCam: string = ""; + // private isChannelReady = false; + // private isInitiator = false; + // private isStarted = false; + @observable remoteVideoAdded: boolean = false; + // localStream: MediaStream | undefined; + // private pc: any; + // remoteStream: MediaStream | undefined; + // private turnReady: boolean | undefined; + // //localVideo: HTMLVideoElement | undefined; + // //remoteVideo: HTMLVideoElement | undefined; + // curRoom: string = ""; + + // private pcConfig = { + // 'iceServers': [{ + // 'urls': 'stun:stun.l.google.com:19302' + // }] + // }; + + // // Set up audio and video regardless of what devices are present. + // private sdpConstraints = { + // offerToReceiveAudio: true, + // offerToReceiveVideo: true + // }; + + componentDidMount() { + DocumentDecorations.Instance.addCloseCall(this.closeConnection); + // setTimeout(() => initialize(), 10000); + // let self = this; + // window.onbeforeunload = function () { + // self.sendMessage('bye'); + // }; + } + + closeConnection: CloseCall = () => { + hangup(); + } + + @action + changeUILook = () => { + this.remoteVideoAdded = true; + } + + // componentWillUnmount() { + // } + + + // init(room: string) { + + // this.curRoom = room; + // let self = this; + + // 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); + // self.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 + '!'); + // self.isChannelReady = true; + // }); + + + // DocServer._socket.on('joined', function (room: string) { + // console.log('joined: ' + room); + // self.isChannelReady = true; + // }); + + + // DocServer._socket.on('log', function (array: any) { + // console.log.apply(console, array); + // }); + + // // This client receives a message + // DocServer._socket.on('message', async function (message: any) { + // console.log('Client received message:', message); + // if (message.message === 'got user media') { + // self.maybeStart(); + // } else if (message.message.type === 'offer') { + // if (!self.isInitiator && !self.isStarted) { + // self.maybeStart(); + // } + // await self.pc.setRemoteDescription(new RTCSessionDescription(message.message)); + // self.doAnswer(); + // } else if (message.message.type === 'answer' && self.isStarted) { + // await self.pc.setRemoteDescription(new RTCSessionDescription(message.message)); + // } else if (message.message.type === 'candidate' && self.isStarted) { + // let candidate = new RTCIceCandidate({ + // sdpMLineIndex: message.message.label, + // candidate: message.message.candidate + // }); + // self.pc.addIceCandidate(candidate); + // } else if (message.message === 'bye' && self.isStarted) { + // self.handleRemoteHangup(); + // } + // }); + + // navigator.mediaDevices.getUserMedia({ + // audio: true, + // video: true + // }) + // .then(this.gotStream) + // .catch(function (e) { + // alert('getUserMedia() error: ' + e.name); + // }); + + // //Trying this one out!!! + // console.log('Getting user media with constraints', this.constraints); + + // if (location.hostname !== 'localhost') { + // this.requestTurn( + // 'https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913' + // ); + // } + + + // } + + + // private sendMessage = (message: any) => { + // console.log('Client sending message: ', message); + // Utils.Emit(DocServer._socket, MessageStore.NotifyRoommates, { message: message, room: this.curRoom }); + // //DocServer._socket.emit('message', message); + // } + + + + // private gotStream = (stream: any) => { + // console.log('Adding local stream.'); + // this.localStream = stream; + // this.localVideoEl!.srcObject = stream; + // this.sendMessage('got user media'); + // if (this.isInitiator) { + // this.maybeStart(); + // } + // } + + // constraints = { + // video: true, + // audio: true + // }; + + + + + + // private maybeStart = () => { + // console.log('>>>>>>> maybeStart() ', this.isStarted, this.localStream, this.isChannelReady); + // if (!this.isStarted && typeof this.localStream !== 'undefined' && this.isChannelReady) { + // console.log('>>>>>> creating peer connection'); + // this.createPeerConnection(); + // this.pc.addStream(this.localStream); + // this.isStarted = true; + // console.log('isInitiator', this.isInitiator); + // if (this.isInitiator) { + // this.doCall(); + // } + // } + // } + + + // // //this will need to be changed to our version of hangUp + // // window.onbeforeunload = function () { + // // sendMessage('bye'); + // // }; + + // private createPeerConnection = () => { + // try { + // this.pc = new RTCPeerConnection(undefined); + // this.pc.onicecandidate = this.handleIceCandidate; + // this.pc.onaddstream = this.handleRemoteStreamAdded; + // this.pc.onremovestream = this.handleRemoteStreamRemoved; + // console.log('Created RTCPeerConnnection'); + // } catch (e) { + // console.log('Failed to create PeerConnection, exception: ' + e.message); + // alert('Cannot create RTCPeerConnection object.'); + // return; + // } + // } + + // private handleIceCandidate = (event: any) => { + // console.log('icecandidate event: ', event); + // if (event.candidate) { + // this.sendMessage({ + // type: 'candidate', + // label: event.candidate.sdpMLineIndex, + // id: event.candidate.sdpMid, + // candidate: event.candidate.candidate + // }); + // } else { + // console.log('End of candidates.'); + // } + // } + + // private handleCreateOfferError = (event: any) => { + // console.log('createOffer() error: ', event); + // } + + // private doCall = () => { + // console.log('Sending offer to peer'); + // this.pc.createOffer(this.setLocalAndSendMessage, this.handleCreateOfferError); + // } + + // private doAnswer = () => { + // console.log('Sending answer to peer.'); + // this.pc.createAnswer().then( + // this.setLocalAndSendMessage, + // this.onCreateSessionDescriptionError + // ); + // } + + // private setLocalAndSendMessage = (sessionDescription: any) => { + // this.pc.setLocalDescription(sessionDescription); + // console.log('setLocalAndSendMessage sending message', sessionDescription); + // this.sendMessage(sessionDescription); + // } + + // private onCreateSessionDescriptionError = (error: any) => { + // console.log('Failed to create session description: ' + error.toString()); + // } + + + // private requestTurn = (turnURL: any) => { + // var turnExists = false; + // let self = this; + // for (var i in this.pcConfig.iceServers) { + // if (this.pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') { + // turnExists = true; + // this.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); + // self.pcConfig.iceServers.push({ + // 'urls': 'turn:' + turnServer.username + '@' + turnServer.turn, + // //'credential': turnServer.password + // }); + // self.turnReady = true; + // } + // }; + // xhr.open('GET', turnURL, true); + // xhr.send(); + // } + // } + // @action + // private handleRemoteStreamAdded = (event: MediaStreamEvent) => { + // console.log('Remote stream added.'); + // this.remoteStream = event.stream!; + // this.peerVideoEl!.srcObject = this.remoteStream; + // this.remoteVideoAdded = true; + // } + + // private handleRemoteStreamRemoved = (event: MediaStreamEvent) => { + // console.log('Remote stream removed. Event: ', event); + // } + + // private hangup = () => { + // console.log('Hanging up.'); + // if (this.pc) { + // stop(); + // this.sendMessage('bye'); + // } + + // if (this.localStream) { + // this.localStream.getTracks().forEach(track => track.stop()); + // } + + // } + + // private handleRemoteHangup = () => { + // console.log('Session terminated.'); + // this.stop(); + // this.isInitiator = false; + + // if (this.localStream) { + // this.localStream.getTracks().forEach(track => track.stop()); + // } + + + // } + + // private stop = () => { + // this.isStarted = false; + // this.pc.close(); + // this.pc = null; + // } + + + + + + + /** + * Function that submits the title entered by user on enter press. + */ + private onEnterKeyDown = (e: React.KeyboardEvent) => { + if (e.keyCode === 13) { + let submittedTitle = this.roomText!.value; + this.roomText!.value = ""; + this.roomText!.blur(); + initialize(submittedTitle, this.changeUILook); + } + } + + + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DashWebRTCVideo, fieldKey); } + + _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}> + <div className="webcam-header">DashWebRTC</div> + <input id="roomName" type="text" placeholder="Enter room name" ref={(e) => this.roomText = e!} onKeyDown={this.onEnterKeyDown} /> + <video id="localVideo" className={"RTCVideo" + (this.remoteVideoAdded ? " side" : " main")} autoPlay playsInline ref={(e) => { + this.localVideoEl = e!; + }}></video> + <video id="remoteVideo" className="RTCVideo main" autoPlay playsInline ref={(e) => { + this.peerVideoEl = e!; + }}></video> + + </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 |