jam-cloud/web/app/assets/javascripts/react-components/stores/WebcamViewer.js.jsx.coffee

387 lines
12 KiB
CoffeeScript

context = window
logger = context.JK.logger
reactContext = if window.opener? then window.opener else window
# make sure this is actually us opening the window, not someone else (by checking for MixerStore)
if window.opener?
try
m = window.opener.MixerStore
catch e
reactContext = window
userAgent = window.navigator.userAgent;
if /iPhone|iPad|iPod|android/i.test(navigator.userAgent)
# iPad or iPhone
reactContext = window
VideoStore = reactContext.VideoStore
VideoActions = reactContext.VideoActions
PlatformStore = reactContext.PlatformStore
ALERT_NAMES = context.JK.ALERT_NAMES;
BackendNumericToBackendString = {
1 : "CIF (352X288)",
2 : "VGA (640X480)",
3 : "4CIF (704X576)",
4 : "1/2WHD (640X360)",
5 : "WHD (1280X720)",
6 : "FHD (1920x1080)"
}
BackendToFrontendFPS = {
1: 30,
2: 24,
3: 20,
4: 15,
5: 10
}
mixins = []
mixins.push(Reflux.listenTo(VideoStore, 'onVideoStateChanged'))
@WebcamViewer = React.createClass({
mixins: mixins
logger: context.JK.logger
visible: false
getInitialState: () ->
{
currentDevice: null
deviceNames: {}
deviceCaps: null
currentCaptureResolution: 0
captureResolutions: {}
frameRates: {}
rescanning: false
}
onVideoStateChanged: (changes) ->
@setState(changes)
render: () ->
if @props.showBackBtn
backBtn = `<a className="hidden button-grey back-btn" onClick={this.back}>BACK</a>`
selectedDevice = this.selectedDeviceName(@state)
# build list of webcams
webcams = []
noneSelected = selectedDevice == null || selectedDevice.length == 0
# the backend does not allow setting no video camera. So if a webcam is selected, prevent un-selecting
if noneSelected
webcams.push `<option key="none" value="" selected={noneSelected}>None Selected</option>`
context._.each @state.deviceNames, (deviceName, deviceGuid) ->
selected = deviceGuid == selectedDevice
webcams.push `<option key={deviceGuid} value={deviceGuid} selected={selected}>{deviceName}</option>`
noWebcams = Object.keys(@state.deviceNames).length == 0
# build list of capture resolutions
captureResolutions = []
# load current settings from backend
captureResolution = @state.currentCaptureResolution
resolutions = @state.captureResolutions
context._.each resolutions, (resolution, resolutionKey, obj) =>
value = resolutionKey
text = resolution
selected = captureResolution.toString() == value.toString()
captureResolutions.push `<option key={value} value={value} selected={selected}>{text}</option>`
testBtnClassNames = {'button-orange' : true, 'webcam-test-btn' : true}
if noWebcams
if PlatformStore.isWindows()
testBtnClassNames.disabled = !@state.videoEnabled
testBtnClasses = classNames(testBtnClassNames)
testBtn = `<a className={testBtnClasses} onClick={this.toggleWebcam}>TEST VIDEO</a>`
else
testBtn = null
else if @state.videoShared
testBtnClassNames.disabled = !@state.videoEnabled
testBtnClasses = classNames(testBtnClassNames)
testBtn = `<a className={testBtnClasses} onClick={this.toggleWebcam}>STOP WEBCAM</a>`
else
testBtnClassNames.disabled = !@state.videoEnabled || noneSelected
testBtnClasses = classNames(testBtnClassNames)
testBtn = `<a className={testBtnClasses} onClick={this.toggleWebcam}>TEST WEBCAM</a>`
if @state.rescanning
rescanning =
`<span className="rescanning-notice">
<span className="spinner-small" />
CHECKING GEAR
</span>`
if @props.show_header
if noWebcams
if PlatformStore.isWindows()
testVideoHelpText = `<span>The TEST VIDEO button will open the JamKazam video window to verify that receiving video works on your system.</span>`
header = `<div className="video-header">
<h2 className="subcaption">video gear:</h2>
<div className="subcaption">
JamKazam does not detect any webcams. You will not be able to send video, but you can still receive it from others. {testVideoHelpText}
</div>
</div>`
else
header =
`<div className="video-header">
<h2 className="subcaption">video gear:</h2>
<div className="subcaption">
Select webcam to use for video in sessions. Verify that you see video from webcam in the external application window (it may be behind this window).
</div>
</div>`
if @state.videoEnabled
disableVideoBtnText = "DISABLE VIDEO"
else
disableVideoBtnText = "ENABLE VIDEO"
if @props.show_disable || !@state.videoEnabled || @state.everDisabled
if @state.videoEnabled
disableHelpBtn = `<a className="ftue-video-disable-help">[?]</a>`
disableBtnClasses = classNames({'button-grey' : true, 'disable-video' : true, 'disabled' : @state.videoShared})
disableVideo =
`<div className="webcam-select-container wizard_control">
<a className={disableBtnClasses} onClick={this.disableVideo}>{disableVideoBtnText}</a>
{disableHelpBtn}
</div>`
`<div className="webcam-viewer">
{header}
<form className="video">
<h2 className="sub-header select-webcam">select webcam:</h2>
<div className="webcam-select-container wizard_control">
<select onChange={this.selectWebcam} disabled={noWebcams || !this.state.videoEnabled}>
{webcams}
</select>
</div>
<h2 className="sub-header select-resolution">select video capture resolution:</h2>
<div className="webcam-resolution-select-container wizard_control">
<select onChange={this.selectResolution} disabled={noWebcams || !this.state.videoEnabled}>
{captureResolutions}
</select>
<a className="ftue-video-settings-help">[?]</a>
</div>
<div className="configure-webcam wizard_control">
{backBtn}
{testBtn}
</div>
{rescanning}
</form>
{disableVideo}
</div>`
componentDidMount: () ->
if @props.isVisible
@beforeShow()
$root = $(@getDOMNode())
$videoSettingsHelp = $root.find('.ftue-video-settings-help')
context.JK.helpBubble($videoSettingsHelp, 'ftue-video-settings', {}, {width:300}) if $videoSettingsHelp.length > 0
$videoSettingsHelp.click(false)
$videoDisableHelp = $root.find('.ftue-video-disable-help')
context.JK.helpBubble($videoDisableHelp, 'ftue-video-disable', {}, {width:300}) if $videoDisableHelp.length > 0
$videoDisableHelp.click(false)
componentWillUpdate: (nextProps, nextState) ->
# protect against non-video clients pointed at video-enabled server from getting into a session
#@logger.debug("webcam devices", nextState.deviceNames, @state.deviceNames)
if !@initialScan?
@initialScan = true
else if @visible
@findChangedWebcams(nextState.deviceNames, @state.deviceNames)
componentWillReceiveProps:(nextProps) ->
if nextProps.isVisible
@beforeShow()
else
@beforeHide()
beforeShow:() ->
@visible = true
VideoActions.refresh()
VideoActions.stopVideo()
context.JK.onBackendEvent(ALERT_NAMES.USB_CONNECTED, 'webcam-viewer', @onUsbDeviceConnected);
context.JK.onBackendEvent(ALERT_NAMES.USB_DISCONNECTED, 'webcam-viewer', @onUsbDeviceDisconnected);
beforeHide: () ->
@visible = false
context.JK.offBackendEvent(ALERT_NAMES.USB_CONNECTED, 'webcam-viewer', @onUsbDeviceConnected);
context.JK.offBackendEvent(ALERT_NAMES.USB_DISCONNECTED, 'webcam-viewer', @onUsbDeviceDisconnected);
if @rescanTimeout?
clearTimeout(@rescanTimeout)
@rescanTimeout = null
@setVideoOff()
onUsbDeviceConnected: () ->
# don't handle USB events when minimized
#return if !context.jamClient.IsFrontendVisible()
logger.debug("USB device connected")
@scheduleRescanSystem(3000)
onUsbDeviceDisconnected:() ->
# don't handle USB events when minimized
#return if !context.jamClient.IsFrontendVisible()
logger.debug("USB device disconnected")
@scheduleRescanSystem(3000)
scheduleRescanSystem: (time) ->
if @rescanTimeout?
clearTimeout(@rescanTimeout)
@rescanTimeout = null
@setState({rescanning: true})
@rescanTimeout = setTimeout(() =>
@setState({rescanning: false})
VideoActions.refresh()
, time)
selectWebcam:(e) ->
e.preventDefault()
device = $(e.target).val()
VideoActions.selectDevice(device, {})
disableVideo: (e) ->
e.preventDefault()
return if @state.videoShared
if @state.videoEnabled
context.JK.Banner.showYesNo({
title: "Disable Video?",
html: "You will not be able to send or receive video.",
yes: =>
VideoActions.setVideoEnabled(false)
})
else
VideoActions.setVideoEnabled(true)
updateBackend: (captureResolution) ->
@logger.debug 'Selecting capture resolution: ', captureResolution
VideoActions.setCaptureResolution(captureResolution)
selectResolution:(e) ->
e.preventDefault()
resolution = $(e.target).val()
@logger.debug 'new capture resolution selected: ' + resolution
if resolution?
@updateBackend(resolution)
setVideoOff:() ->
VideoActions.stopVideo()
back: () =>
window.location = '/client#/account'
toggleWebcam:(e) ->
e.preventDefault()
return unless this.state.videoEnabled
$toggleBtn = $(e.target)
# we should only do this if no device is currently selected
$root = $(@getDOMNode())
$select = $root.find('.webcam-select-container select')
if Object.keys(@state.deviceNames).length == 0
context.JK.Banner.showYesNo({
yes_text: 'RUN TEST',
title: "Run Video Test?",
html: "A video window will show up with changing colors and shapes for 10 seconds. The test was successful if you were able to see the changing colors. Close the window once the colors and shapes stop changing.",
yes: =>
VideoActions.testVideo()
})
else
device = $select.val()
#VideoActions.selectDevice(device, {})
if VideoStore.videoShared
VideoActions.stopVideo()
else
VideoActions.toggleVideo()
#if this.isVideoShared()
# $toggleBtn.removeClass("selected")
# VideoActions.stopVideo()
# @setState({videoShared: false})
#else
# $toggleBtn.addClass("selected")
# VideoActions.startVideo()
# @setState({videoShared: true})
selectedDeviceName:(state) ->
webcamName = null
# protect against non-video clients pointed at video-enabled server from getting into a session
webcam = state.currentDevice
#@logger.debug("currently selected video device", webcam)
if (webcam? && Object.keys(webcam).length>0)
webcamName = Object.keys(webcam)[0]
webcamName
findChangedWebcams: (newList, oldList) ->
newKeys = Object.keys(newList)
oldKeys = Object.keys(oldList)
webcamSelect = $(@getDOMNode()).find('.webcam-select-container select')
if newKeys.length > oldKeys.length
for newKey in newKeys
if oldKeys.indexOf(newKey) == -1
newWebcam = newList[newKey]
@logger.debug("new webcam found: " + newWebcam, newKey)
context.JK.prodBubble(webcamSelect, 'new-webcam-found', {name: newWebcam}, {positions:['right']})
break
else if newKeys.length < oldKeys.length
for oldKey in oldKeys
if newKeys.indexOf(oldKey) == -1
oldWebcam = oldList[oldKey]
@logger.debug("webcam no longer found: " + oldWebcam)
context.JK.prodBubble(webcamSelect, 'old-webcam-lost', {name: oldWebcam}, {positions:['right']})
break
}
)