320 lines
9.2 KiB
CoffeeScript
320 lines
9.2 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
|
|
|
|
VideoStore = reactContext.VideoStore
|
|
VideoActions = reactContext.VideoActions
|
|
|
|
ALERT_NAMES = context.JK.ALERT_NAMES;
|
|
|
|
BackendToFrontend = {
|
|
1 : "CIF (352x288)",
|
|
2 : "VGA (640x480)",
|
|
3 : "4CIF (704x576)",
|
|
4 : "1/2 720p HD (640x360)",
|
|
5 : "720p HD (1280x720)",
|
|
6 : "1080p HD (1920x1080)"
|
|
}
|
|
|
|
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
|
|
}
|
|
FrontendToBackend = {}
|
|
for key, value of BackendToFrontend
|
|
FrontendToBackend[value] = key
|
|
|
|
mixins = []
|
|
mixins.push(Reflux.listenTo(VideoStore, 'onVideoStateChanged'))
|
|
|
|
|
|
@WebcamViewer = React.createClass({
|
|
|
|
mixins: mixins
|
|
logger: context.JK.logger
|
|
|
|
getInitialState: () ->
|
|
{
|
|
currentDevice: null
|
|
deviceNames: {}
|
|
deviceCaps: null
|
|
currentResolution: 0
|
|
currentFrameRate: 0
|
|
encodeResolutions: {}
|
|
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 = []
|
|
context._.each @state.deviceNames, (deviceName, deviceGuid) ->
|
|
selected = deviceName == selectedDevice
|
|
webcams.push `<option key={deviceGuid} value={deviceGuid} selected={selected}>{deviceName}</option>`
|
|
|
|
# build list of capture resolutions
|
|
|
|
captureResolutions = []
|
|
# load current settings from backend
|
|
currentResolution = @state.currentResolution
|
|
currentFrameRate = @state.currentFrameRate
|
|
|
|
# protect against non-video clients pointed at video-enabled server from getting into a session
|
|
resolutions = @state.encodeResolutions
|
|
frames = @state.frameRates
|
|
@logger.debug 'FOUND THESE RESOLUTIONS', resolutions
|
|
@logger.debug 'FOUND THESE FPS', frames
|
|
context._.each resolutions, (resolution, resolutionKey, obj) =>
|
|
|
|
#{1: "CIF (352X288)", 2: "VGA (640X480)", 3: "4CIF (704X576)", 4: "1/2WHD (640X360)", 5: "WHD (1280X720)", 6: "FHD (1920x1080)"}
|
|
context._.each frames, (frame, key, obj) =>
|
|
|
|
frontendResolution = BackendToFrontend[resolutionKey]
|
|
|
|
@logger.error("unknown resolution! #{resolution}", BackendToFrontend) unless frontendResolution
|
|
|
|
value = "#{resolutionKey}|#{frame}"
|
|
text = "#{frontendResolution} at #{frame} fps"
|
|
|
|
selected = currentResolution + '|' + currentFrameRate == value
|
|
|
|
captureResolutions.push `<option key={value} value={value} selected={selected}>{text}</option>`
|
|
|
|
autoSelect = false
|
|
if currentResolution == 0
|
|
@logger.warn("current resolution not specified; defaulting to VGA")
|
|
autoSelect = true
|
|
currentResolution = 2
|
|
if currentFrameRate == 0
|
|
autoSelect = true
|
|
@logger.warn("current frame rate not specified; defaulting to 30")
|
|
currentFrameRate = 30
|
|
else
|
|
convertedFrameRate = BackendToFrontendFPS[currentFrameRate]
|
|
@logger.debug("translating FPS: backend numeric #{currentFrameRate} to #{convertedFrameRate}")
|
|
currentFrameRate = convertedFrameRate
|
|
|
|
# backend needs to be same as frontend
|
|
if autoSelect
|
|
@updateBackend(currentResolution, currentFrameRate)
|
|
|
|
if @state.videoShared
|
|
toggleText = 'STOP WEBCAM'
|
|
else
|
|
toggleText = 'TEST WEBCAM'
|
|
|
|
if @state.rescanning
|
|
rescanning =
|
|
`<span className="rescanning-notice">
|
|
<span className="spinner-small" />
|
|
CHECKING GEAR
|
|
</span>`
|
|
|
|
`<form className="video">
|
|
<h2 className="sub-header select-webcam">select webcam:</h2>
|
|
<div className="webcam-select-container wizard_control">
|
|
<select onChange={this.selectWebcam}>
|
|
{webcams}
|
|
</select>
|
|
</div>
|
|
<h2 className="sub-header select-resolution">select video capture resolution & frame rate:</h2>
|
|
<div className="webcam-resolution-select-container wizard_control">
|
|
<select onChange={this.selectResolution}>
|
|
{captureResolutions}
|
|
</select>
|
|
<a className="ftue-video-settings-help">[?]</a>
|
|
</div>
|
|
<div className="configure-webcam wizard_control">
|
|
{backBtn}
|
|
<a className="button-orange webcam-test-btn" onClick={this.toggleWebcam}>{toggleText}</a>
|
|
</div>
|
|
{rescanning}
|
|
</form>`
|
|
|
|
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)
|
|
|
|
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
|
|
@findChangedWebcams(nextState.deviceNames, @state.deviceNames)
|
|
|
|
componentWillReceiveProps:(nextProps) ->
|
|
if nextProps.isVisible
|
|
@beforeShow()
|
|
else
|
|
@beforeHide()
|
|
|
|
beforeShow:() ->
|
|
|
|
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: () ->
|
|
|
|
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, {})
|
|
|
|
updateBackend: (selectedResolution, selectedFps) ->
|
|
@logger.debug 'Selecting webcam resolution: ', selectedResolution
|
|
@logger.debug 'Selecting webcam fps: ', selectedFps
|
|
|
|
VideoActions.setVideoEncodeResolution(selectedResolution)
|
|
VideoActions.setSendFrameRate(selectedFps)
|
|
|
|
selectResolution:(e) ->
|
|
e.preventDefault()
|
|
|
|
resolution = $(e.target).val()
|
|
@logger.debug 'new capture resolution selected: ' + resolution
|
|
|
|
if resolution?
|
|
bits = resolution.split('|')
|
|
selectedResolution = bits[0]
|
|
selectedFps = bits[1]
|
|
@updateBackend(selectedResolution, selectedFps)
|
|
|
|
setVideoOff:() ->
|
|
VideoActions.stopVideo()
|
|
|
|
back: () =>
|
|
window.location = '/client#/account'
|
|
|
|
toggleWebcam:(e) ->
|
|
e.preventDefault()
|
|
$toggleBtn = $(e.target)
|
|
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="None Configured"
|
|
# 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
|
|
|
|
|
|
}
|
|
)
|
|
|
|
|