Add ability to set stream audio playing in background

This commit is contained in:
Max Goodhart
2020-08-26 23:28:04 -07:00
parent 93a29ecfac
commit d8e51776e9
6 changed files with 59 additions and 9 deletions

View File

@@ -29,6 +29,9 @@ function Overlay({ config, views, streams }) {
const isListening = viewState.matches( const isListening = viewState.matches(
'displaying.running.audio.listening', 'displaying.running.audio.listening',
) )
const isBackgroundListening = viewState.matches(
'displaying.running.audio.background',
)
const isBlurred = viewState.matches('displaying.running.video.blurred') const isBlurred = viewState.matches('displaying.running.video.blurred')
const isLoading = viewState.matches('displaying.loading') const isLoading = viewState.matches('displaying.loading')
return ( return (
@@ -51,7 +54,7 @@ function Overlay({ config, views, streams }) {
</> </>
)} )}
</span> </span>
{isListening && <SoundIcon />} {(isListening || isBackgroundListening) && <SoundIcon />}
</StreamTitle> </StreamTitle>
)} )}
{isLoading && <LoadingSpinner />} {isLoading && <LoadingSpinner />}

View File

@@ -257,6 +257,10 @@ export default class StreamWindow extends EventEmitter {
} }
} }
setViewBackgroundListening(viewIdx, listening) {
this.sendViewEvent(viewIdx, listening ? 'BACKGROUND' : 'UNBACKGROUND')
}
setViewBlurred(viewIdx, blurred) { setViewBlurred(viewIdx, blurred) {
this.sendViewEvent(viewIdx, blurred ? 'BLUR' : 'UNBLUR') this.sendViewEvent(viewIdx, blurred ? 'BLUR' : 'UNBLUR')
} }

View File

@@ -270,6 +270,8 @@ async function main() {
const onMessage = async (msg, respond) => { const onMessage = async (msg, respond) => {
if (msg.type === 'set-listening-view') { if (msg.type === 'set-listening-view') {
streamWindow.setListeningView(msg.viewIdx) streamWindow.setListeningView(msg.viewIdx)
} else if (msg.type === 'set-view-background-listening') {
streamWindow.setViewBackgroundListening(msg.viewIdx, msg.listening)
} else if (msg.type === 'set-view-blurred') { } else if (msg.type === 'set-view-blurred') {
streamWindow.setViewBlurred(msg.viewIdx, msg.blurred) streamWindow.setViewBlurred(msg.viewIdx, msg.blurred)
} else if (msg.type === 'set-custom-streams') { } else if (msg.type === 'set-custom-streams') {

View File

@@ -141,6 +141,8 @@ const viewStateMachine = Machine(
on: { on: {
MUTE: '.muted', MUTE: '.muted',
UNMUTE: '.listening', UNMUTE: '.listening',
BACKGROUND: '.background',
UNBACKGROUND: '.muted',
}, },
states: { states: {
muted: { muted: {
@@ -149,6 +151,13 @@ const viewStateMachine = Machine(
listening: { listening: {
entry: 'unmuteAudio', entry: 'unmuteAudio',
}, },
background: {
on: {
// Ignore normal audio swapping.
MUTE: {},
},
entry: 'unmuteAudio',
},
}, },
}, },
video: { video: {

View File

@@ -1,5 +1,6 @@
const operatorActions = new Set([ const operatorActions = new Set([
'set-listening-view', 'set-listening-view',
'set-view-background-listening',
'set-view-blurred', 'set-view-blurred',
'set-custom-streams', 'set-custom-streams',
'reload-view', 'reload-view',

View File

@@ -15,6 +15,7 @@ import {
import { State } from 'xstate' import { State } from 'xstate'
import styled, { createGlobalStyle } from 'styled-components' import styled, { createGlobalStyle } from 'styled-components'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import Color from 'color'
import '../index.css' import '../index.css'
import { idxInBox } from '../geometry' import { idxInBox } from '../geometry'
@@ -139,6 +140,9 @@ function useStreamwallConnection(wsEndpoint) {
const isListening = state.matches( const isListening = state.matches(
'displaying.running.audio.listening', 'displaying.running.audio.listening',
) )
const isBackgroundListening = state.matches(
'displaying.running.audio.background',
)
const isBlurred = state.matches('displaying.running.video.blurred') const isBlurred = state.matches('displaying.running.video.blurred')
for (const space of pos.spaces) { for (const space of pos.spaces) {
if (!newStateIdxMap.has(space)) { if (!newStateIdxMap.has(space)) {
@@ -147,6 +151,7 @@ function useStreamwallConnection(wsEndpoint) {
Object.assign(newStateIdxMap.get(space), { Object.assign(newStateIdxMap.get(space), {
state, state,
isListening, isListening,
isBackgroundListening,
isBlurred, isBlurred,
spaces: pos.spaces, spaces: pos.spaces,
}) })
@@ -332,6 +337,14 @@ function App({ wsEndpoint, role }) {
}) })
}, []) }, [])
const handleSetBackgroundListening = useCallback((viewIdx, listening) => {
send({
type: 'set-view-background-listening',
viewIdx,
listening,
})
}, [])
const handleSetBlurred = useCallback((idx, blurred) => { const handleSetBlurred = useCallback((idx, blurred) => {
send({ send({
type: 'set-view-blurred', type: 'set-view-blurred',
@@ -504,8 +517,12 @@ function App({ wsEndpoint, role }) {
<StyledGridLine> <StyledGridLine>
{range(0, gridCount).map((x) => { {range(0, gridCount).map((x) => {
const idx = gridCount * y + x const idx = gridCount * y + x
const { isListening = false, isBlurred = false, state } = const {
stateIdxMap.get(idx) || {} isListening = false,
isBackgroundListening = false,
isBlurred = false,
state,
} = stateIdxMap.get(idx) || {}
const { streamId } = sharedState.views?.[idx] || '' const { streamId } = sharedState.views?.[idx] || ''
const isDragHighlighted = const isDragHighlighted =
dragStart !== undefined && dragStart !== undefined &&
@@ -517,6 +534,7 @@ function App({ wsEndpoint, role }) {
isError={state && state.matches('displaying.error')} isError={state && state.matches('displaying.error')}
isDisplaying={state && state.matches('displaying')} isDisplaying={state && state.matches('displaying')}
isListening={isListening} isListening={isListening}
isBackgroundListening={isBackgroundListening}
isBlurred={isBlurred} isBlurred={isBlurred}
isHighlighted={isDragHighlighted} isHighlighted={isDragHighlighted}
isSwapping={idx === swapStartIdx} isSwapping={idx === swapStartIdx}
@@ -528,6 +546,7 @@ function App({ wsEndpoint, role }) {
onBlur={handleBlurInput} onBlur={handleBlurInput}
onChangeSpace={handleSetView} onChangeSpace={handleSetView}
onSetListening={handleSetListening} onSetListening={handleSetListening}
onSetBackgroundListening={handleSetBackgroundListening}
onSetBlurred={handleSetBlurred} onSetBlurred={handleSetBlurred}
onReloadView={handleReloadView} onReloadView={handleReloadView}
onSwapView={handleSwapView} onSwapView={handleSwapView}
@@ -722,6 +741,7 @@ function GridInput({
isDisplaying, isDisplaying,
isError, isError,
isListening, isListening,
isBackgroundListening,
isBlurred, isBlurred,
isHighlighted, isHighlighted,
isSwapping, isSwapping,
@@ -732,6 +752,7 @@ function GridInput({
onFocus, onFocus,
onBlur, onBlur,
onSetListening, onSetListening,
onSetBackgroundListening,
onSetBlurred, onSetBlurred,
onReloadView, onReloadView,
onSwapView, onSwapView,
@@ -762,8 +783,17 @@ function GridInput({
[idx, onChangeSpace], [idx, onChangeSpace],
) )
const handleListeningClick = useCallback( const handleListeningClick = useCallback(
() => onSetListening(idx, !isListening), (ev) =>
[idx, onSetListening, isListening], ev.shiftKey || isBackgroundListening
? onSetBackgroundListening(idx, !isBackgroundListening)
: onSetListening(idx, !isListening),
[
idx,
onSetListening,
onSetBackgroundListening,
isListening,
isBackgroundListening,
],
) )
const handleBlurClick = useCallback(() => onSetBlurred(idx, !isBlurred), [ const handleBlurClick = useCallback(() => onSetBlurred(idx, !isBlurred), [
idx, idx,
@@ -839,7 +869,8 @@ function GridInput({
)} )}
{roleCan(role, 'set-listening-view') && ( {roleCan(role, 'set-listening-view') && (
<StyledButton <StyledButton
isActive={isListening} isActive={isListening || isBackgroundListening}
activeColor={isListening ? 'red' : Color('red').desaturate(0.5)}
onClick={handleListeningClick} onClick={handleListeningClick}
tabIndex={1} tabIndex={1}
> >
@@ -931,11 +962,11 @@ const StyledButton = styled.button`
background: #ccc; background: #ccc;
border-radius: 5px; border-radius: 5px;
${({ isActive }) => ${({ isActive, activeColor }) =>
isActive && isActive &&
` `
border-color: red; border-color: ${activeColor};
background: #c77; background: ${Color(activeColor).desaturate(0.5).lighten(0.5)};
`}; `};
&:focus { &:focus {