Skip to content
This repository was archived by the owner on Aug 21, 2024. It is now read-only.

Commit e9bb19c

Browse files
authored
Refactor Network and Media State (#7887)
* remove multiple sources of truth for media consumers, remove redundant actions * remove duplicated state and actions for media * more cleanup
1 parent 6ee0ba1 commit e9bb19c

14 files changed

Lines changed: 160 additions & 332 deletions

File tree

packages/client-core/src/common/services/LocationInstanceConnectionService.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Paginated } from '@feathersjs/feathers'
2-
import { none } from '@hookstate/core'
2+
import { none, State } from '@hookstate/core'
33
import { useEffect } from 'react'
44

55
import { Instance } from '@etherealengine/common/src/interfaces/Instance'
@@ -53,6 +53,12 @@ export const LocationInstanceState = defineState({
5353
})
5454
})
5555

56+
export function useWorldNetwork() {
57+
const worldNetworkState = useState(getMutableState(NetworkState).networks)
58+
const worldHostId = useState(getMutableState(NetworkState).hostIds.world)
59+
return worldHostId.value ? (worldNetworkState[worldHostId.value] as State<SocketWebRTCClientNetwork>) : null
60+
}
61+
5662
export function useWorldInstance() {
5763
const worldInstanceState = useState(getMutableState(LocationInstanceState).instances)
5864
const worldHostId = useState(getMutableState(NetworkState).hostIds.world)

packages/client-core/src/common/services/MediaInstanceConnectionService.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ export const MediaInstanceState = defineState({
5353
})
5454
})
5555

56+
export function useMediaNetwork() {
57+
const mediaNetworkState = useState(getMutableState(NetworkState).networks)
58+
const mediaHostId = useState(getMutableState(NetworkState).hostIds.media)
59+
return mediaHostId.value ? (mediaNetworkState[mediaHostId.value] as State<SocketWebRTCClientNetwork>) : null
60+
}
61+
5662
export function useMediaInstance() {
5763
const mediaInstanceState = useState(getMutableState(MediaInstanceState).instances)
5864
const mediaHostId = useState(getMutableState(NetworkState).hostIds.media)

packages/client-core/src/components/ConferenceMode/index.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ import classNames from 'classnames'
33
import React from 'react'
44

55
import { MediaInstanceState } from '@etherealengine/client-core/src/common/services/MediaInstanceConnectionService'
6-
import { MediaState } from '@etherealengine/client-core/src/media/services/MediaStreamService'
76
import { AuthState } from '@etherealengine/client-core/src/user/services/AuthService'
87
import { NetworkUserState } from '@etherealengine/client-core/src/user/services/NetworkUserService'
98
import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine'
109
import { screenshareVideoDataChannelType } from '@etherealengine/engine/src/networking/NetworkState'
1110
import { getMutableState, useHookstate } from '@etherealengine/hyperflux'
1211

12+
import { MediaStreamState } from '../../transports/MediaStreams'
13+
import { NearbyUsersState } from '../../transports/UpdateNearbyUsersSystem'
1314
import ConferenceModeParticipant from './ConferenceModeParticipant'
1415
import styles from './index.module.scss'
1516

1617
const ConferenceMode = (): JSX.Element => {
17-
const mediaState = useHookstate(getMutableState(MediaState))
18-
const nearbyLayerUsers = mediaState.nearbyLayerUsers
18+
const nearbyLayerUsers = useHookstate(getMutableState(NearbyUsersState).nearbyLayerUsers)
1919
const selfUserId = useHookstate(getMutableState(AuthState).user.id)
2020
const userState = useHookstate(getMutableState(NetworkUserState))
2121
const channelConnectionState = useHookstate(getMutableState(MediaInstanceState))
@@ -36,13 +36,19 @@ const ConferenceMode = (): JSX.Element => {
3636
: []
3737
: []
3838

39-
const consumers = mediaState.consumers.value
39+
const consumers = network.consumers
4040
const screenShareConsumers =
4141
consumers?.filter((consumer) => consumer.appData.mediaTag === screenshareVideoDataChannelType) || []
4242

43+
const mediaStreamState = useHookstate(getMutableState(MediaStreamState))
44+
const isScreenVideoEnabled =
45+
mediaStreamState.screenVideoProducer.value != null && !mediaStreamState.screenShareVideoPaused.value
46+
const isScreenAudioEnabled =
47+
mediaStreamState.screenShareAudioPaused.value != null && !mediaStreamState.screenShareAudioPaused.value
48+
4349
let totalScreens = 1
4450

45-
if (mediaState.isScreenAudioEnabled.value || mediaState.isScreenVideoEnabled.value) {
51+
if (isScreenVideoEnabled || isScreenAudioEnabled) {
4652
totalScreens += 1
4753
}
4854

@@ -63,7 +69,7 @@ const ConferenceMode = (): JSX.Element => {
6369
[styles['multi-grid']]: totalScreens === 3 || totalScreens > 4
6470
})}
6571
>
66-
{(mediaState.isScreenAudioEnabled.value || mediaState.isScreenVideoEnabled.value) && (
72+
{(isScreenVideoEnabled || isScreenAudioEnabled) && (
6773
<ConferenceModeParticipant type={'screen'} peerID={network.peerID} key={'screen_' + network.peerID} />
6874
)}
6975
<ConferenceModeParticipant type={'cam'} peerID={network.peerID} key={'cam_' + network.peerID} />

packages/client-core/src/components/MediaIconsBox/index.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import React, { useEffect, useState } from 'react'
2-
import { Navigate, useNavigate } from 'react-router-dom'
32

43
import { useMediaInstanceConnectionState } from '@etherealengine/client-core/src/common/services/MediaInstanceConnectionService'
5-
import { useMediaStreamState } from '@etherealengine/client-core/src/media/services/MediaStreamService'
64
import { useLocationState } from '@etherealengine/client-core/src/social/services/LocationService'
75
import {
8-
toggleFaceTracking,
96
toggleMicrophonePaused,
107
toggleScreenshare,
118
toggleWebcamPaused
@@ -19,11 +16,11 @@ import { dispatchAction, getMutableState, useHookstate } from '@etherealengine/h
1916
import Icon from '@etherealengine/ui/src/Icon'
2017

2118
import { VrIcon } from '../../common/components/Icons/VrIcon'
19+
import { MediaStreamState } from '../../transports/MediaStreams'
2220
import { useShelfStyles } from '../Shelves/useShelfStyles'
2321
import styles from './index.module.scss'
2422

2523
export const MediaIconsBox = () => {
26-
const navigate = useNavigate()
2724
const [hasAudioDevice, setHasAudioDevice] = useState(false)
2825
const [hasVideoDevice, setHasVideoDevice] = useState(false)
2926
const { topShelfStyle } = useShelfStyles()
@@ -32,18 +29,19 @@ export const MediaIconsBox = () => {
3229
const channelConnectionState = useMediaInstanceConnectionState()
3330
const mediaHostId = Engine.instance.mediaNetwork?.hostId
3431
const currentChannelInstanceConnection = mediaHostId && channelConnectionState.instances[mediaHostId].ornull
35-
const mediastream = useMediaStreamState()
3632
const videoEnabled = currentLocation?.locationSetting?.value
3733
? currentLocation?.locationSetting?.videoEnabled?.value
3834
: false
3935
const audioEnabled = currentLocation?.locationSetting?.value
4036
? currentLocation?.locationSetting?.audioEnabled?.value
4137
: false
4238

43-
const isMotionCaptureEnabled = mediastream.isMotionCaptureEnabled
44-
const isCamVideoEnabled = mediastream.isCamVideoEnabled
45-
const isCamAudioEnabled = mediastream.isCamAudioEnabled
46-
const isScreenVideoEnabled = mediastream.isScreenVideoEnabled
39+
const mediaStreamState = useHookstate(getMutableState(MediaStreamState))
40+
const isMotionCaptureEnabled = mediaStreamState.faceTracking.value
41+
const isCamVideoEnabled = mediaStreamState.camVideoProducer.value != null && !mediaStreamState.videoPaused.value
42+
const isCamAudioEnabled = mediaStreamState.camAudioProducer.value != null && !mediaStreamState.audioPaused.value
43+
const isScreenVideoEnabled =
44+
mediaStreamState.screenVideoProducer.value != null && !mediaStreamState.screenShareVideoPaused.value
4745

4846
const engineState = useEngineState()
4947
const xrState = useHookstate(getMutableState(XRState))
@@ -75,12 +73,12 @@ export const MediaIconsBox = () => {
7573
<button
7674
type="button"
7775
id="UserAudio"
78-
className={styles.iconContainer + ' ' + (isCamAudioEnabled.value ? styles.on : '')}
76+
className={styles.iconContainer + ' ' + (isCamAudioEnabled ? styles.on : '')}
7977
onClick={toggleMicrophonePaused}
8078
onPointerUp={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
8179
onPointerEnter={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
8280
>
83-
<Icon type={isCamAudioEnabled.value ? 'Mic' : 'MicOff'} />
81+
<Icon type={isCamAudioEnabled ? 'Mic' : 'MicOff'} />
8482
</button>
8583
) : null}
8684
{videoEnabled &&
@@ -91,17 +89,17 @@ export const MediaIconsBox = () => {
9189
<button
9290
type="button"
9391
id="UserVideo"
94-
className={styles.iconContainer + ' ' + (isCamVideoEnabled.value ? styles.on : '')}
92+
className={styles.iconContainer + ' ' + (isCamVideoEnabled ? styles.on : '')}
9593
onClick={toggleWebcamPaused}
9694
onPointerUp={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
9795
onPointerEnter={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
9896
>
99-
<Icon type={isCamVideoEnabled.value ? 'Videocam' : 'VideocamOff'} />
97+
<Icon type={isCamVideoEnabled ? 'Videocam' : 'VideocamOff'} />
10098
</button>
10199
<button
102100
type="button"
103101
id="UserPoseTracking"
104-
className={styles.iconContainer + ' ' + (isMotionCaptureEnabled.value ? styles.on : '')}
102+
className={styles.iconContainer + ' ' + (isMotionCaptureEnabled ? styles.on : '')}
105103
onClick={() => window.open('/capture', '_blank')}
106104
onPointerUp={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
107105
onPointerEnter={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
@@ -111,7 +109,7 @@ export const MediaIconsBox = () => {
111109
<button
112110
type="button"
113111
id="UserScreenSharing"
114-
className={styles.iconContainer + ' ' + (isScreenVideoEnabled.value ? styles.on : '')}
112+
className={styles.iconContainer + ' ' + (isScreenVideoEnabled ? styles.on : '')}
115113
onClick={toggleScreenshare}
116114
onPointerUp={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}
117115
onPointerEnter={() => AudioEffectPlayer.instance.play(AudioEffectPlayer.SOUNDS.ui)}

packages/client-core/src/components/UserMediaWindow/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import hark from 'hark'
44
import React, { useEffect, useRef, useState } from 'react'
55
import { useTranslation } from 'react-i18next'
66

7-
import { useMediaStreamState } from '@etherealengine/client-core/src/media/services/MediaStreamService'
87
import { useLocationState } from '@etherealengine/client-core/src/social/services/LocationService'
98
import {
109
globalMuteProducer,

packages/client-core/src/media/PeerMedia.tsx

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine'
55
import { MessageTypes } from '@etherealengine/engine/src/networking/enums/MessageTypes'
66
import {
77
MediaTagType,
8+
NetworkState,
89
screenshareAudioDataChannelType,
910
screenshareVideoDataChannelType,
1011
webcamAudioDataChannelType,
1112
webcamVideoDataChannelType
1213
} from '@etherealengine/engine/src/networking/NetworkState'
13-
import { getMutableState, useHookstate } from '@etherealengine/hyperflux'
14+
import { getMutableState, State, useHookstate } from '@etherealengine/hyperflux'
1415

15-
import { MediaInstanceState } from '../common/services/MediaInstanceConnectionService'
16+
import {
17+
MediaInstanceState,
18+
useMediaInstance,
19+
useMediaNetwork
20+
} from '../common/services/MediaInstanceConnectionService'
1621
import { MediaStreamState } from '../transports/MediaStreams'
1722
import {
1823
createPeerMediaChannels,
@@ -24,13 +29,14 @@ import {
2429
ProducerExtension,
2530
SocketWebRTCClientNetwork
2631
} from '../transports/SocketWebRTCClientFunctions'
32+
import { NearbyUsersState } from '../transports/UpdateNearbyUsersSystem'
2733
import { AuthState } from '../user/services/AuthService'
2834
import { NetworkUserState } from '../user/services/NetworkUserService'
29-
import { MediaState } from './services/MediaStreamService'
3035

3136
export const getMediaChannels = (network: SocketWebRTCClientNetwork, consumers: ConsumerExtension[]) => {
32-
const mediaState = getMutableState(MediaState)
33-
const nearbyLayerUsers = mediaState.nearbyLayerUsers
37+
const nearbyUsersState = getMutableState(NearbyUsersState)
38+
const mediaStreamState = getMutableState(MediaStreamState)
39+
const nearbyLayerUsers = nearbyUsersState.nearbyLayerUsers
3440
const selfUserId = getMutableState(AuthState).user.id
3541
const userState = getMutableState(NetworkUserState)
3642
const channelConnectionState = getMutableState(MediaInstanceState)
@@ -56,9 +62,9 @@ export const getMediaChannels = (network: SocketWebRTCClientNetwork, consumers:
5662

5763
/** always put own peer first */
5864
const selfPeerID = network?.peerID ?? 'self'
59-
if (mediaState.isScreenVideoEnabled.value)
65+
if (mediaStreamState.screenVideoProducer.value != null && !mediaStreamState.screenShareVideoPaused.value)
6066
mediaChannels.push({ peerID: selfPeerID, mediaTag: screenshareVideoDataChannelType })
61-
if (mediaState.isScreenAudioEnabled.value)
67+
if (mediaStreamState.screenAudioProducer.value != null && !mediaStreamState.screenShareAudioPaused.value)
6268
mediaChannels.push({ peerID: selfPeerID, mediaTag: screenshareAudioDataChannelType })
6369
mediaChannels.push({ peerID: selfPeerID, mediaTag: webcamVideoDataChannelType })
6470
mediaChannels.push({ peerID: selfPeerID, mediaTag: webcamAudioDataChannelType })
@@ -88,7 +94,7 @@ export const getMediaChannels = (network: SocketWebRTCClientNetwork, consumers:
8894
/**
8995
* Sets media stream state for a peer
9096
*/
91-
const PeerConsumer = (props: {
97+
const PeerMedia = (props: {
9298
channel: ConsumerExtension | ProducerExtension
9399
peerID: PeerID
94100
mediaTag: MediaTagType
@@ -128,13 +134,13 @@ const PeerConsumer = (props: {
128134
peerMediaChannelState.audioProducerPaused.set(true)
129135
peerMediaChannelState.audioProducerGlobalMute.set(true)
130136
} else {
131-
const videoConsumer = network.consumers?.find(
137+
const videoConsumer = network.consumers.find(
132138
(c) =>
133139
c.appData.peerID === peerID &&
134140
c.producerId === producerId &&
135141
c.appData.mediaTag === (isScreen ? screenshareVideoDataChannelType : webcamVideoDataChannelType)
136142
)
137-
const audioConsumer = network.consumers?.find(
143+
const audioConsumer = network.consumers.find(
138144
(c) =>
139145
c.appData.peerID === peerID &&
140146
c.producerId === producerId &&
@@ -159,12 +165,12 @@ const PeerConsumer = (props: {
159165
peerMediaChannelState.audioProducerPaused.set(false)
160166
peerMediaChannelState.audioProducerGlobalMute.set(false)
161167
} else {
162-
const videoConsumer = network.consumers?.find(
168+
const videoConsumer = network.consumers.find(
163169
(c) =>
164170
c.appData.peerID === peerID &&
165171
c.appData.mediaTag === (isScreen ? screenshareVideoDataChannelType : webcamVideoDataChannelType)
166172
)
167-
const audioConsumer = network.consumers?.find(
173+
const audioConsumer = network.consumers.find(
168174
(c) =>
169175
c.appData.peerID === peerID &&
170176
c.appData.mediaTag === (isScreen ? screenshareAudioDataChannelType : webcamAudioDataChannelType)
@@ -213,12 +219,12 @@ const PeerConsumer = (props: {
213219
}
214220
}
215221
} else {
216-
const videoConsumer = network.consumers?.find(
222+
const videoConsumer = network.consumers.find(
217223
(c) =>
218224
c.appData.peerID === peerID &&
219225
c.appData.mediaTag === (isScreen ? screenshareVideoDataChannelType : webcamVideoDataChannelType)
220226
)
221-
const audioConsumer = network.consumers?.find(
227+
const audioConsumer = network.consumers.find(
222228
(c) =>
223229
c.appData.peerID === peerID &&
224230
c.appData.mediaTag === (isScreen ? screenshareAudioDataChannelType : webcamAudioDataChannelType)
@@ -304,15 +310,19 @@ const PeerConsumer = (props: {
304310
return null
305311
}
306312

307-
export const PeerMedia = () => {
308-
const mediaState = useHookstate(getMutableState(MediaState))
313+
export const PeerConsumers = () => {
314+
const nearbyUsersState = useHookstate(getMutableState(NearbyUsersState))
315+
309316
const mediaStreamState = useHookstate(getMutableState(MediaStreamState))
310317
const peerMediaChannelState = useHookstate(getMutableState(PeerMediaChannelState))
311-
const network = Engine.instance.mediaNetwork as SocketWebRTCClientNetwork
318+
319+
const networkState = useMediaNetwork()
320+
const network = networkState?.value
312321

313322
// create a peer media stream for each peer with a consumer
314323
useEffect(() => {
315-
const mediaChannels = getMediaChannels(network, mediaState.consumers.get({ noproxy: true }))
324+
if (!network) return
325+
const mediaChannels = getMediaChannels(network, network.consumers)
316326
for (const consumer of mediaChannels) {
317327
if (!peerMediaChannelState.value[consumer.peerID]) {
318328
createPeerMediaChannels(consumer.peerID)
@@ -325,8 +335,8 @@ export const PeerMedia = () => {
325335
}
326336
}
327337
}, [
328-
mediaState.nearbyLayerUsers.length,
329-
mediaState.consumers.length,
338+
nearbyUsersState.nearbyLayerUsers.length,
339+
networkState?.consumers?.length,
330340
mediaStreamState.videoStream,
331341
mediaStreamState.audioStream,
332342
mediaStreamState.screenAudioProducer,
@@ -339,14 +349,15 @@ export const PeerMedia = () => {
339349
channel: ConsumerExtension | ProducerExtension
340350
}[]
341351

342-
mediaChannels.push(
343-
...mediaState.consumers.value.map((media) => {
344-
return { peerID: media.appData.peerID, mediaTag: media.appData.mediaTag, channel: media }
345-
})
346-
)
352+
if (network)
353+
mediaChannels.push(
354+
...network.consumers.map((media: ConsumerExtension) => {
355+
return { peerID: media.appData.peerID, mediaTag: media.appData.mediaTag, channel: media }
356+
})
357+
)
347358

348359
// own peer id
349-
const peerID = network?.peerID ?? 'self'
360+
const peerID = network?.peerID ?? ('self' as PeerID)
350361

351362
if (mediaStreamState.camVideoProducer.value)
352363
mediaChannels.push({
@@ -378,7 +389,7 @@ export const PeerMedia = () => {
378389
{mediaChannels
379390
.filter(({ peerID }) => peerMediaChannelState[peerID].value)
380391
.map(({ channel, peerID, mediaTag }) => (
381-
<PeerConsumer channel={channel} peerID={peerID} mediaTag={mediaTag} key={peerID + '-' + mediaTag} />
392+
<PeerMedia channel={channel} peerID={peerID} mediaTag={mediaTag} key={peerID + '-' + mediaTag} />
382393
))}
383394
</>
384395
)

0 commit comments

Comments
 (0)