@@ -2,13 +2,15 @@ import type { MutableRefObject } from 'react'
2
2
import type { ActorRefFrom } from 'xstate'
3
3
import { assign , fromPromise , setup } from 'xstate'
4
4
import type { AppMachineContext } from '@src/lib/types'
5
+ import { EngineConnectionStateType } from '@src/lang/std/engineConnection'
5
6
6
7
export enum EngineStreamState {
7
8
WaitingForDependencies = 'waiting-for-dependencies' ,
8
9
WaitingForMediaStream = 'waiting-for-media-stream' ,
9
10
WaitingToPlay = 'waiting-to-play' ,
10
11
Playing = 'playing' ,
11
12
Reconfiguring = 'reconfiguring' ,
13
+ Pausing = 'pausing' ,
12
14
Paused = 'paused' ,
13
15
Stopped = 'stopped' ,
14
16
// The is the state in-between Paused and Playing *specifically that order*.
@@ -239,25 +241,55 @@ export const engineStreamMachine = setup({
239
241
console . warn ( 'Save remote camera state timed out' , e )
240
242
}
241
243
242
- // Make sure we're on the next frame for no flickering between canvas
243
- // and the video elements.
244
- window . requestAnimationFrame (
245
- ( ) =>
246
- void ( async ( ) => {
247
- // Destroy the media stream. We will re-establish it. We could
248
- // leave everything at pausing, preventing video decoders from running
249
- // but we can do even better by significantly reducing network
250
- // cards also.
251
- context . mediaStream ?. getVideoTracks ( ) [ 0 ] . stop ( )
252
- context . mediaStream = null
253
-
254
- if ( context . videoRef . current ) {
255
- context . videoRef . current . srcObject = null
256
- }
257
-
258
- rootContext . engineCommandManager . tearDown ( { idleMode : true } )
259
- } ) ( )
260
- )
244
+ await new Promise < void > ( ( resolve , reject ) => {
245
+ // Make sure we're on the next frame for no flickering between canvas
246
+ // and the video elements.
247
+ window . requestAnimationFrame (
248
+ ( ) =>
249
+ void ( async ( ) => {
250
+ // Destroy the media stream. We will re-establish it. We could
251
+ // leave everything at pausing, preventing video decoders from running
252
+ // but we can do even better by significantly reducing network
253
+ // cards also.
254
+ context . mediaStream ?. getVideoTracks ( ) [ 0 ] . stop ( )
255
+ context . mediaStream = null
256
+
257
+ if ( context . videoRef . current ) {
258
+ context . videoRef . current . srcObject = null
259
+ }
260
+
261
+ let oldEngineConnection =
262
+ rootContext . engineCommandManager . engineConnection
263
+ setTimeout ( ( ) => {
264
+ rootContext . engineCommandManager . tearDown ( { idleMode : true } )
265
+ } , 1000 )
266
+
267
+ let timeoutCheckId : ReturnType < typeof setTimeout >
268
+ const timeoutEjectId = setTimeout ( ( ) => {
269
+ clearTimeout ( timeoutCheckId )
270
+ reject ( )
271
+ } , 5000 )
272
+
273
+ const checkClosed = ( ) => {
274
+ timeoutCheckId = setTimeout ( ( ) => {
275
+ if (
276
+ oldEngineConnection ?. state ?. type !==
277
+ EngineConnectionStateType . Disconnected
278
+ ) {
279
+ checkClosed ( )
280
+ return
281
+ }
282
+ // Finally disconnected.
283
+ clearTimeout ( timeoutEjectId )
284
+ resolve ( )
285
+ } , 100 )
286
+ }
287
+ checkClosed ( )
288
+ } ) ( )
289
+ )
290
+ } )
291
+
292
+ return { }
261
293
}
262
294
) ,
263
295
} ,
@@ -356,7 +388,7 @@ export const engineStreamMachine = setup({
356
388
target : EngineStreamState . Reconfiguring ,
357
389
} ,
358
390
[ EngineStreamTransition . Pause ] : {
359
- target : EngineStreamState . Paused ,
391
+ target : EngineStreamState . Pausing ,
360
392
} ,
361
393
[ EngineStreamTransition . Stop ] : {
362
394
target : EngineStreamState . Stopped ,
@@ -374,14 +406,18 @@ export const engineStreamMachine = setup({
374
406
onDone : [ { target : EngineStreamState . Playing } ] ,
375
407
} ,
376
408
} ,
377
- [ EngineStreamState . Paused ] : {
409
+ [ EngineStreamState . Pausing ] : {
378
410
invoke : {
379
411
src : EngineStreamTransition . Pause ,
380
412
input : ( args ) => ( {
381
413
context : args . context ,
382
414
rootContext : args . self . system . get ( 'root' ) . getSnapshot ( ) . context ,
383
415
} ) ,
416
+ onDone : [ { target : EngineStreamState . Paused } ] ,
417
+ onError : [ { target : EngineStreamState . Stopped } ] ,
384
418
} ,
419
+ } ,
420
+ [ EngineStreamState . Paused ] : {
385
421
on : {
386
422
[ EngineStreamTransition . Resume ] : {
387
423
target : EngineStreamState . Resuming ,
0 commit comments