@videojs/spf 10.0.0-beta.22 → 10.0.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{dev/core → default/core/actors}/create-machine-actor.js +3 -3
- package/dist/default/core/actors/create-machine-actor.js.map +1 -0
- package/dist/default/core/{create-transition-actor.js → actors/create-transition-actor.js} +3 -3
- package/dist/default/core/actors/create-transition-actor.js.map +1 -0
- package/dist/default/core/composition/create-composition.js +85 -0
- package/dist/default/core/composition/create-composition.js.map +1 -0
- package/dist/default/core/composition/share-signals.js +37 -0
- package/dist/default/core/composition/share-signals.js.map +1 -0
- package/dist/{dev/core → default/core/reactors}/create-machine-reactor.js +4 -4
- package/dist/default/core/reactors/create-machine-reactor.js.map +1 -0
- package/dist/default/core/signals/primitives.js +33 -11
- package/dist/default/core/signals/primitives.js.map +1 -1
- package/dist/default/core/{task.js → tasks/task.js} +2 -2
- package/dist/default/core/tasks/task.js.map +1 -0
- package/dist/default/dom.js +9 -10
- package/dist/default/hls.js +3 -0
- package/dist/default/index.js +12 -3
- package/dist/default/index.js.map +1 -1
- package/dist/default/media/abr/quality-selection.js +83 -0
- package/dist/default/media/abr/quality-selection.js.map +1 -0
- package/dist/default/{core → media}/buffer/back-buffer.js +2 -2
- package/dist/default/media/buffer/back-buffer.js.map +1 -0
- package/dist/{dev/core → default/media}/buffer/forward-buffer.js +14 -2
- package/dist/default/media/buffer/forward-buffer.js.map +1 -0
- package/dist/{dev/dom/media → default/media/dom/mse}/append-segment.js +1 -1
- package/dist/default/media/dom/mse/append-segment.js.map +1 -0
- package/dist/default/{dom/media → media/dom/mse}/buffer-flusher.js +1 -1
- package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -0
- package/dist/default/media/dom/mse/duration.js +78 -0
- package/dist/default/media/dom/mse/duration.js.map +1 -0
- package/dist/default/media/dom/mse/end-of-stream.js +20 -0
- package/dist/default/media/dom/mse/end-of-stream.js.map +1 -0
- package/dist/default/{dom/media → media/dom/mse}/mediasource-setup.js +63 -18
- package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -0
- package/dist/default/{dom/text/parse-vtt-segment.js → media/dom/text/resolve-vtt-segment.js} +5 -5
- package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -0
- package/dist/default/media/dom/text/text-track-slots.js +69 -0
- package/dist/default/media/dom/text/text-track-slots.js.map +1 -0
- package/dist/{dev/core → default/media}/hls/parse-attributes.js +1 -1
- package/dist/default/media/hls/parse-attributes.js.map +1 -0
- package/dist/{dev/core → default/media}/hls/parse-media-playlist.js +1 -1
- package/dist/default/media/hls/parse-media-playlist.js.map +1 -0
- package/dist/{dev/core → default/media}/hls/parse-multivariant.js +2 -2
- package/dist/default/media/hls/parse-multivariant.js.map +1 -0
- package/dist/default/{core → media}/hls/resolve-url.js +1 -1
- package/dist/default/media/hls/resolve-url.js.map +1 -0
- package/dist/default/media/primitives/select-tracks.js +45 -0
- package/dist/default/media/primitives/select-tracks.js.map +1 -0
- package/dist/default/media/types/index.js +36 -0
- package/dist/default/media/types/index.js.map +1 -0
- package/dist/default/media/utils/preload.js +22 -0
- package/dist/default/media/utils/preload.js.map +1 -0
- package/dist/default/media/utils/track-selection.js +47 -0
- package/dist/default/media/utils/track-selection.js.map +1 -0
- package/dist/default/media/utils/tracks.js +103 -0
- package/dist/default/media/utils/tracks.js.map +1 -0
- package/dist/default/{core/abr → network}/bandwidth-estimator.js +6 -5
- package/dist/default/network/bandwidth-estimator.js.map +1 -0
- package/dist/{dev/dom → default}/network/chunked-stream-iterable.js +1 -1
- package/dist/default/network/chunked-stream-iterable.js.map +1 -0
- package/dist/{dev/core/abr → default/network}/ewma.js +1 -1
- package/dist/default/network/ewma.js.map +1 -0
- package/dist/default/network/fetch.js +109 -0
- package/dist/default/network/fetch.js.map +1 -0
- package/dist/{dev/dom/features/segment-loader-actor.js → default/playback/actors/dom/segment-loader.js} +24 -15
- package/dist/default/playback/actors/dom/segment-loader.js.map +1 -0
- package/dist/{dev/dom/media/source-buffer-actor.js → default/playback/actors/dom/source-buffer.js} +8 -8
- package/dist/default/playback/actors/dom/source-buffer.js.map +1 -0
- package/dist/{dev/dom/features/text-tracks-actor.js → default/playback/actors/dom/text-tracks.js} +7 -3
- package/dist/default/playback/actors/dom/text-tracks.js.map +1 -0
- package/dist/default/playback/actors/text-track-segment-loader.js +135 -0
- package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -0
- package/dist/default/playback/behaviors/calculate-presentation-duration.js +58 -0
- package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -0
- package/dist/default/playback/behaviors/dom/end-of-stream.js +178 -0
- package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -0
- package/dist/default/playback/behaviors/dom/load-segments.js +177 -0
- package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -0
- package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +173 -0
- package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
- package/dist/default/playback/behaviors/dom/setup-mediasource.js +89 -0
- package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -0
- package/dist/default/playback/behaviors/dom/setup-text-track-actors.js +54 -0
- package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
- package/dist/default/playback/behaviors/dom/sync-text-tracks.js +99 -0
- package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
- package/dist/default/playback/behaviors/dom/track-current-time.js +46 -0
- package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -0
- package/dist/default/playback/behaviors/dom/track-load-triggers.js +94 -0
- package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -0
- package/dist/default/playback/behaviors/dom/track-playback-rate.js +37 -0
- package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -0
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +90 -0
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
- package/dist/default/playback/behaviors/quality-switching.js +96 -0
- package/dist/default/playback/behaviors/quality-switching.js.map +1 -0
- package/dist/default/playback/behaviors/resolve-presentation.js +85 -0
- package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -0
- package/dist/default/playback/behaviors/resolve-track.js +97 -0
- package/dist/default/playback/behaviors/resolve-track.js.map +1 -0
- package/dist/default/playback/behaviors/select-tracks.js +132 -0
- package/dist/default/playback/behaviors/select-tracks.js.map +1 -0
- package/dist/default/playback/behaviors/sync-preload.js +59 -0
- package/dist/default/playback/behaviors/sync-preload.js.map +1 -0
- package/dist/default/playback/behaviors/track-types.js +61 -0
- package/dist/default/playback/behaviors/track-types.js.map +1 -0
- package/dist/default/{dom/playback-engine → playback/engines/hls}/adapter.js +36 -25
- package/dist/default/playback/engines/hls/adapter.js.map +1 -0
- package/dist/default/playback/engines/hls/engine.js +102 -0
- package/dist/default/playback/engines/hls/engine.js.map +1 -0
- package/dist/dev/core/{actor.d.ts → actors/actor.d.ts} +2 -2
- package/dist/dev/core/actors/actor.d.ts.map +1 -0
- package/dist/dev/core/actors/create-machine-actor.d.ts +125 -0
- package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -0
- package/dist/{default/core → dev/core/actors}/create-machine-actor.js +3 -3
- package/dist/dev/core/actors/create-machine-actor.js.map +1 -0
- package/dist/dev/core/actors/create-transition-actor.d.ts +42 -0
- package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -0
- package/dist/dev/core/{create-transition-actor.js → actors/create-transition-actor.js} +3 -3
- package/dist/dev/core/actors/create-transition-actor.js.map +1 -0
- package/dist/dev/core/composition/create-composition.d.ts +274 -0
- package/dist/dev/core/composition/create-composition.d.ts.map +1 -0
- package/dist/dev/core/composition/create-composition.js +85 -0
- package/dist/dev/core/composition/create-composition.js.map +1 -0
- package/dist/dev/core/composition/share-signals.d.ts +45 -0
- package/dist/dev/core/composition/share-signals.d.ts.map +1 -0
- package/dist/dev/core/composition/share-signals.js +37 -0
- package/dist/dev/core/composition/share-signals.js.map +1 -0
- package/dist/dev/core/machine.d.ts +0 -1
- package/dist/dev/core/machine.d.ts.map +1 -1
- package/dist/dev/core/reactors/create-machine-reactor.d.ts +93 -0
- package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -0
- package/dist/{default/core → dev/core/reactors}/create-machine-reactor.js +4 -4
- package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -0
- package/dist/dev/core/signals/primitives.d.ts +38 -1
- package/dist/dev/core/signals/primitives.d.ts.map +1 -1
- package/dist/dev/core/signals/primitives.js +33 -11
- package/dist/dev/core/signals/primitives.js.map +1 -1
- package/dist/dev/core/tasks/task.d.ts +115 -0
- package/dist/dev/core/tasks/task.d.ts.map +1 -0
- package/dist/dev/core/{task.js → tasks/task.js} +2 -2
- package/dist/dev/core/tasks/task.js.map +1 -0
- package/dist/dev/dom.d.ts +9 -10
- package/dist/dev/dom.js +9 -10
- package/dist/dev/hls.d.ts +3 -0
- package/dist/dev/hls.js +3 -0
- package/dist/dev/index.d.ts +15 -3
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +12 -3
- package/dist/dev/index.js.map +1 -1
- package/dist/dev/media/abr/quality-selection.d.ts +22 -0
- package/dist/dev/media/abr/quality-selection.d.ts.map +1 -0
- package/dist/dev/media/abr/quality-selection.js +83 -0
- package/dist/dev/media/abr/quality-selection.js.map +1 -0
- package/dist/dev/media/buffer/back-buffer.d.ts +14 -0
- package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -0
- package/dist/dev/{core → media}/buffer/back-buffer.js +2 -2
- package/dist/dev/media/buffer/back-buffer.js.map +1 -0
- package/dist/dev/media/buffer/forward-buffer.d.ts +14 -0
- package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -0
- package/dist/{default/core → dev/media}/buffer/forward-buffer.js +14 -2
- package/dist/dev/media/buffer/forward-buffer.js.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/append-segment.d.ts +1 -1
- package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -0
- package/dist/{default/dom/media → dev/media/dom/mse}/append-segment.js +1 -1
- package/dist/dev/media/dom/mse/append-segment.js.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/buffer-flusher.d.ts +1 -1
- package/dist/dev/media/dom/mse/buffer-flusher.d.ts.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/buffer-flusher.js +1 -1
- package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -0
- package/dist/dev/media/dom/mse/duration.js +78 -0
- package/dist/dev/media/dom/mse/duration.js.map +1 -0
- package/dist/dev/media/dom/mse/end-of-stream.js +20 -0
- package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/mediasource-setup.js +63 -18
- package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -0
- package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts +12 -0
- package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -0
- package/dist/dev/{dom/text/parse-vtt-segment.js → media/dom/text/resolve-vtt-segment.js} +5 -5
- package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -0
- package/dist/dev/media/dom/text/text-track-slots.d.ts +31 -0
- package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -0
- package/dist/dev/media/dom/text/text-track-slots.js +69 -0
- package/dist/dev/media/dom/text/text-track-slots.js.map +1 -0
- package/dist/{default/core → dev/media}/hls/parse-attributes.js +1 -1
- package/dist/dev/media/hls/parse-attributes.js.map +1 -0
- package/dist/{default/core → dev/media}/hls/parse-media-playlist.js +1 -1
- package/dist/dev/media/hls/parse-media-playlist.js.map +1 -0
- package/dist/{default/core → dev/media}/hls/parse-multivariant.js +2 -2
- package/dist/dev/media/hls/parse-multivariant.js.map +1 -0
- package/dist/dev/{core → media}/hls/resolve-url.js +1 -1
- package/dist/dev/media/hls/resolve-url.js.map +1 -0
- package/dist/dev/media/primitives/select-tracks.js +45 -0
- package/dist/dev/media/primitives/select-tracks.js.map +1 -0
- package/dist/dev/{core → media}/types/index.d.ts +30 -2
- package/dist/dev/media/types/index.d.ts.map +1 -0
- package/dist/dev/media/types/index.js +36 -0
- package/dist/dev/media/types/index.js.map +1 -0
- package/dist/dev/media/utils/preload.js +22 -0
- package/dist/dev/media/utils/preload.js.map +1 -0
- package/dist/dev/media/utils/track-selection.js +47 -0
- package/dist/dev/media/utils/track-selection.js.map +1 -0
- package/dist/dev/media/utils/tracks.js +103 -0
- package/dist/dev/media/utils/tracks.js.map +1 -0
- package/dist/dev/{core/abr → network}/bandwidth-estimator.d.ts +17 -2
- package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -0
- package/dist/dev/{core/abr → network}/bandwidth-estimator.js +6 -5
- package/dist/dev/network/bandwidth-estimator.js.map +1 -0
- package/dist/{default/dom → dev}/network/chunked-stream-iterable.js +1 -1
- package/dist/dev/network/chunked-stream-iterable.js.map +1 -0
- package/dist/{default/core/abr → dev/network}/ewma.js +1 -1
- package/dist/dev/network/ewma.js.map +1 -0
- package/dist/dev/network/fetch.js +109 -0
- package/dist/dev/network/fetch.js.map +1 -0
- package/dist/dev/playback/actors/dom/segment-loader.d.ts +36 -0
- package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -0
- package/dist/{default/dom/features/segment-loader-actor.js → dev/playback/actors/dom/segment-loader.js} +24 -15
- package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -0
- package/dist/dev/{dom/media/source-buffer-actor.d.ts → playback/actors/dom/source-buffer.d.ts} +5 -5
- package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -0
- package/dist/{default/dom/media/source-buffer-actor.js → dev/playback/actors/dom/source-buffer.js} +8 -8
- package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -0
- package/dist/dev/playback/actors/dom/text-tracks.d.ts +1 -0
- package/dist/{default/dom/features/text-tracks-actor.js → dev/playback/actors/dom/text-tracks.js} +7 -3
- package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -0
- package/dist/dev/playback/actors/text-track-segment-loader.d.ts +59 -0
- package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -0
- package/dist/dev/playback/actors/text-track-segment-loader.js +135 -0
- package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -0
- package/dist/dev/playback/actors/text-tracks.d.ts +42 -0
- package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +17 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.js +58 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/end-of-stream.js +178 -0
- package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/load-segments.d.ts +62 -0
- package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/load-segments.js +177 -0
- package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +173 -0
- package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-mediasource.js +89 -0
- package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +31 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js +54 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +99 -0
- package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +34 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.js +46 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +48 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.js +94 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +34 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.js +37 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +90 -0
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
- package/dist/dev/playback/behaviors/quality-switching.js +96 -0
- package/dist/dev/playback/behaviors/quality-switching.js.map +1 -0
- package/dist/dev/playback/behaviors/resolve-presentation.d.ts +7 -0
- package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/resolve-presentation.js +85 -0
- package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -0
- package/dist/dev/playback/behaviors/resolve-track.js +97 -0
- package/dist/dev/playback/behaviors/resolve-track.js.map +1 -0
- package/dist/dev/playback/behaviors/select-tracks.js +132 -0
- package/dist/dev/playback/behaviors/select-tracks.js.map +1 -0
- package/dist/dev/playback/behaviors/sync-preload.js +59 -0
- package/dist/dev/playback/behaviors/sync-preload.js.map +1 -0
- package/dist/dev/playback/behaviors/track-types.js +61 -0
- package/dist/dev/playback/behaviors/track-types.js.map +1 -0
- package/dist/dev/{dom/playback-engine → playback/engines/hls}/adapter.d.ts +14 -10
- package/dist/dev/playback/engines/hls/adapter.d.ts.map +1 -0
- package/dist/dev/{dom/playback-engine → playback/engines/hls}/adapter.js +36 -25
- package/dist/dev/playback/engines/hls/adapter.js.map +1 -0
- package/dist/dev/playback/engines/hls/engine.d.ts +177 -0
- package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -0
- package/dist/dev/playback/engines/hls/engine.js +102 -0
- package/dist/dev/playback/engines/hls/engine.js.map +1 -0
- package/package.json +8 -9
- package/dist/default/core/abr/bandwidth-estimator.js.map +0 -1
- package/dist/default/core/abr/ewma.js.map +0 -1
- package/dist/default/core/abr/quality-selection.js +0 -53
- package/dist/default/core/abr/quality-selection.js.map +0 -1
- package/dist/default/core/buffer/back-buffer.js.map +0 -1
- package/dist/default/core/buffer/forward-buffer.js.map +0 -1
- package/dist/default/core/create-machine-actor.js.map +0 -1
- package/dist/default/core/create-machine-reactor.js.map +0 -1
- package/dist/default/core/create-transition-actor.js.map +0 -1
- package/dist/default/core/features/calculate-presentation-duration.js +0 -53
- package/dist/default/core/features/calculate-presentation-duration.js.map +0 -1
- package/dist/default/core/features/quality-switching.js +0 -69
- package/dist/default/core/features/quality-switching.js.map +0 -1
- package/dist/default/core/features/resolve-presentation.js +0 -73
- package/dist/default/core/features/resolve-presentation.js.map +0 -1
- package/dist/default/core/features/resolve-track.js +0 -66
- package/dist/default/core/features/resolve-track.js.map +0 -1
- package/dist/default/core/features/select-tracks.js +0 -130
- package/dist/default/core/features/select-tracks.js.map +0 -1
- package/dist/default/core/features/sync-preload-attribute.js +0 -26
- package/dist/default/core/features/sync-preload-attribute.js.map +0 -1
- package/dist/default/core/hls/parse-attributes.js.map +0 -1
- package/dist/default/core/hls/parse-media-playlist.js.map +0 -1
- package/dist/default/core/hls/parse-multivariant.js.map +0 -1
- package/dist/default/core/hls/resolve-url.js.map +0 -1
- package/dist/default/core/task.js.map +0 -1
- package/dist/default/core/types/index.js +0 -15
- package/dist/default/core/types/index.js.map +0 -1
- package/dist/default/core/utils/generate-id.js +0 -21
- package/dist/default/core/utils/generate-id.js.map +0 -1
- package/dist/default/core/utils/track-selection.js +0 -39
- package/dist/default/core/utils/track-selection.js.map +0 -1
- package/dist/default/dom/features/end-of-stream.js +0 -145
- package/dist/default/dom/features/end-of-stream.js.map +0 -1
- package/dist/default/dom/features/load-segments.js +0 -192
- package/dist/default/dom/features/load-segments.js.map +0 -1
- package/dist/default/dom/features/load-text-track-cues.js +0 -104
- package/dist/default/dom/features/load-text-track-cues.js.map +0 -1
- package/dist/default/dom/features/segment-loader-actor.js.map +0 -1
- package/dist/default/dom/features/setup-mediasource.js +0 -48
- package/dist/default/dom/features/setup-mediasource.js.map +0 -1
- package/dist/default/dom/features/setup-sourcebuffer.js +0 -78
- package/dist/default/dom/features/setup-sourcebuffer.js.map +0 -1
- package/dist/default/dom/features/sync-text-tracks.js +0 -95
- package/dist/default/dom/features/sync-text-tracks.js.map +0 -1
- package/dist/default/dom/features/text-track-segment-loader-actor.js +0 -55
- package/dist/default/dom/features/text-track-segment-loader-actor.js.map +0 -1
- package/dist/default/dom/features/text-tracks-actor.js.map +0 -1
- package/dist/default/dom/features/track-current-time.js +0 -49
- package/dist/default/dom/features/track-current-time.js.map +0 -1
- package/dist/default/dom/features/track-playback-initiated.js +0 -66
- package/dist/default/dom/features/track-playback-initiated.js.map +0 -1
- package/dist/default/dom/features/track-playback-rate.js +0 -32
- package/dist/default/dom/features/track-playback-rate.js.map +0 -1
- package/dist/default/dom/features/update-duration.js +0 -78
- package/dist/default/dom/features/update-duration.js.map +0 -1
- package/dist/default/dom/media/append-segment.js.map +0 -1
- package/dist/default/dom/media/buffer-flusher.js.map +0 -1
- package/dist/default/dom/media/mediasource-setup.js.map +0 -1
- package/dist/default/dom/media/source-buffer-actor.js.map +0 -1
- package/dist/default/dom/network/chunked-stream-iterable.js.map +0 -1
- package/dist/default/dom/network/fetch.js +0 -54
- package/dist/default/dom/network/fetch.js.map +0 -1
- package/dist/default/dom/playback-engine/adapter.js.map +0 -1
- package/dist/default/dom/playback-engine/engine.js +0 -142
- package/dist/default/dom/playback-engine/engine.js.map +0 -1
- package/dist/default/dom/playback-engine.js +0 -4
- package/dist/default/dom/text/parse-vtt-segment.js.map +0 -1
- package/dist/dev/core/abr/bandwidth-estimator.d.ts.map +0 -1
- package/dist/dev/core/abr/bandwidth-estimator.js.map +0 -1
- package/dist/dev/core/abr/ewma.js.map +0 -1
- package/dist/dev/core/abr/quality-selection.js +0 -53
- package/dist/dev/core/abr/quality-selection.js.map +0 -1
- package/dist/dev/core/actor.d.ts.map +0 -1
- package/dist/dev/core/buffer/back-buffer.js.map +0 -1
- package/dist/dev/core/buffer/forward-buffer.js.map +0 -1
- package/dist/dev/core/create-machine-actor.d.ts +0 -12
- package/dist/dev/core/create-machine-actor.d.ts.map +0 -1
- package/dist/dev/core/create-machine-actor.js.map +0 -1
- package/dist/dev/core/create-machine-reactor.d.ts +0 -8
- package/dist/dev/core/create-machine-reactor.d.ts.map +0 -1
- package/dist/dev/core/create-machine-reactor.js.map +0 -1
- package/dist/dev/core/create-transition-actor.d.ts +0 -23
- package/dist/dev/core/create-transition-actor.d.ts.map +0 -1
- package/dist/dev/core/create-transition-actor.js.map +0 -1
- package/dist/dev/core/features/calculate-presentation-duration.js +0 -53
- package/dist/dev/core/features/calculate-presentation-duration.js.map +0 -1
- package/dist/dev/core/features/quality-switching.js +0 -69
- package/dist/dev/core/features/quality-switching.js.map +0 -1
- package/dist/dev/core/features/resolve-presentation.js +0 -73
- package/dist/dev/core/features/resolve-presentation.js.map +0 -1
- package/dist/dev/core/features/resolve-track.js +0 -66
- package/dist/dev/core/features/resolve-track.js.map +0 -1
- package/dist/dev/core/features/select-tracks.js +0 -130
- package/dist/dev/core/features/select-tracks.js.map +0 -1
- package/dist/dev/core/features/sync-preload-attribute.js +0 -26
- package/dist/dev/core/features/sync-preload-attribute.js.map +0 -1
- package/dist/dev/core/hls/parse-attributes.js.map +0 -1
- package/dist/dev/core/hls/parse-media-playlist.js.map +0 -1
- package/dist/dev/core/hls/parse-multivariant.js.map +0 -1
- package/dist/dev/core/hls/resolve-url.js.map +0 -1
- package/dist/dev/core/task.js.map +0 -1
- package/dist/dev/core/types/index.d.ts.map +0 -1
- package/dist/dev/core/types/index.js +0 -15
- package/dist/dev/core/types/index.js.map +0 -1
- package/dist/dev/core/utils/generate-id.js +0 -21
- package/dist/dev/core/utils/generate-id.js.map +0 -1
- package/dist/dev/core/utils/track-selection.d.ts +0 -16
- package/dist/dev/core/utils/track-selection.d.ts.map +0 -1
- package/dist/dev/core/utils/track-selection.js +0 -39
- package/dist/dev/core/utils/track-selection.js.map +0 -1
- package/dist/dev/dom/features/end-of-stream.js +0 -145
- package/dist/dev/dom/features/end-of-stream.js.map +0 -1
- package/dist/dev/dom/features/load-segments.d.ts +0 -72
- package/dist/dev/dom/features/load-segments.d.ts.map +0 -1
- package/dist/dev/dom/features/load-segments.js +0 -192
- package/dist/dev/dom/features/load-segments.js.map +0 -1
- package/dist/dev/dom/features/load-text-track-cues.d.ts +0 -85
- package/dist/dev/dom/features/load-text-track-cues.d.ts.map +0 -1
- package/dist/dev/dom/features/load-text-track-cues.js +0 -104
- package/dist/dev/dom/features/load-text-track-cues.js.map +0 -1
- package/dist/dev/dom/features/segment-loader-actor.d.ts +0 -1
- package/dist/dev/dom/features/segment-loader-actor.js.map +0 -1
- package/dist/dev/dom/features/setup-mediasource.js +0 -48
- package/dist/dev/dom/features/setup-mediasource.js.map +0 -1
- package/dist/dev/dom/features/setup-sourcebuffer.d.ts +0 -9
- package/dist/dev/dom/features/setup-sourcebuffer.d.ts.map +0 -1
- package/dist/dev/dom/features/setup-sourcebuffer.js +0 -78
- package/dist/dev/dom/features/setup-sourcebuffer.js.map +0 -1
- package/dist/dev/dom/features/sync-text-tracks.js +0 -95
- package/dist/dev/dom/features/sync-text-tracks.js.map +0 -1
- package/dist/dev/dom/features/text-track-segment-loader-actor.d.ts +0 -12
- package/dist/dev/dom/features/text-track-segment-loader-actor.d.ts.map +0 -1
- package/dist/dev/dom/features/text-track-segment-loader-actor.js +0 -55
- package/dist/dev/dom/features/text-track-segment-loader-actor.js.map +0 -1
- package/dist/dev/dom/features/text-tracks-actor.d.ts +0 -31
- package/dist/dev/dom/features/text-tracks-actor.d.ts.map +0 -1
- package/dist/dev/dom/features/text-tracks-actor.js.map +0 -1
- package/dist/dev/dom/features/track-current-time.d.ts +0 -40
- package/dist/dev/dom/features/track-current-time.d.ts.map +0 -1
- package/dist/dev/dom/features/track-current-time.js +0 -49
- package/dist/dev/dom/features/track-current-time.js.map +0 -1
- package/dist/dev/dom/features/track-playback-initiated.d.ts +0 -46
- package/dist/dev/dom/features/track-playback-initiated.d.ts.map +0 -1
- package/dist/dev/dom/features/track-playback-initiated.js +0 -66
- package/dist/dev/dom/features/track-playback-initiated.js.map +0 -1
- package/dist/dev/dom/features/track-playback-rate.d.ts +0 -34
- package/dist/dev/dom/features/track-playback-rate.d.ts.map +0 -1
- package/dist/dev/dom/features/track-playback-rate.js +0 -32
- package/dist/dev/dom/features/track-playback-rate.js.map +0 -1
- package/dist/dev/dom/features/update-duration.js +0 -78
- package/dist/dev/dom/features/update-duration.js.map +0 -1
- package/dist/dev/dom/media/append-segment.d.ts.map +0 -1
- package/dist/dev/dom/media/append-segment.js.map +0 -1
- package/dist/dev/dom/media/buffer-flusher.d.ts.map +0 -1
- package/dist/dev/dom/media/buffer-flusher.js.map +0 -1
- package/dist/dev/dom/media/mediasource-setup.js.map +0 -1
- package/dist/dev/dom/media/source-buffer-actor.d.ts.map +0 -1
- package/dist/dev/dom/media/source-buffer-actor.js.map +0 -1
- package/dist/dev/dom/network/chunked-stream-iterable.js.map +0 -1
- package/dist/dev/dom/network/fetch.js +0 -54
- package/dist/dev/dom/network/fetch.js.map +0 -1
- package/dist/dev/dom/playback-engine/adapter.d.ts.map +0 -1
- package/dist/dev/dom/playback-engine/adapter.js.map +0 -1
- package/dist/dev/dom/playback-engine/engine.d.ts +0 -124
- package/dist/dev/dom/playback-engine/engine.d.ts.map +0 -1
- package/dist/dev/dom/playback-engine/engine.js +0 -142
- package/dist/dev/dom/playback-engine/engine.js.map +0 -1
- package/dist/dev/dom/playback-engine.d.ts +0 -4
- package/dist/dev/dom/playback-engine.js +0 -4
- package/dist/dev/dom/text/parse-vtt-segment.d.ts +0 -12
- package/dist/dev/dom/text/parse-vtt-segment.d.ts.map +0 -1
- package/dist/dev/dom/text/parse-vtt-segment.js.map +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//#region src/playback/behaviors/track-types.ts
|
|
2
|
+
/**
|
|
3
|
+
* **Per-type config bundles for per-type behavior variants.**
|
|
4
|
+
*
|
|
5
|
+
* Each `*_TYPE_CONFIG` constant names the per-type slot keys that
|
|
6
|
+
* per-type-variant setup-shape helpers consume. Variants reference the
|
|
7
|
+
* shared constant at their `defineBehavior` setup body rather than
|
|
8
|
+
* constructing the config inline, so the per-type identity (which state
|
|
9
|
+
* slot, which context slot, which discriminant) lives in one place per
|
|
10
|
+
* type.
|
|
11
|
+
*
|
|
12
|
+
* Variants spread their composition-time `config` over the defaults so
|
|
13
|
+
* engines can layer composition-supplied additions on top (e.g. a
|
|
14
|
+
* custom fetch closure, a non-default segment resolver). Defaults
|
|
15
|
+
* first, engine config second.
|
|
16
|
+
*
|
|
17
|
+
* Helpers continue to consume their slice via the existing typed-key
|
|
18
|
+
* generics (`<K extends SelectedTrackKey>` etc.); the extra fields on
|
|
19
|
+
* the config object (carrying facets other helpers care about) are fine
|
|
20
|
+
* under structural typing.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Type-identity bundle for video-track-typed behaviors.
|
|
24
|
+
*
|
|
25
|
+
* @see setupVideoBufferActors, loadVideoSegments
|
|
26
|
+
*/
|
|
27
|
+
const VIDEO_TYPE_CONFIG = {
|
|
28
|
+
type: "video",
|
|
29
|
+
selectedKey: "selectedVideoTrackId",
|
|
30
|
+
actorKey: "videoBufferActor",
|
|
31
|
+
loaderKey: "videoSegmentLoaderActor"
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Type-identity bundle for audio-track-typed behaviors.
|
|
35
|
+
*
|
|
36
|
+
* @see setupAudioBufferActors, loadAudioSegments
|
|
37
|
+
*/
|
|
38
|
+
const AUDIO_TYPE_CONFIG = {
|
|
39
|
+
type: "audio",
|
|
40
|
+
selectedKey: "selectedAudioTrackId",
|
|
41
|
+
actorKey: "audioBufferActor",
|
|
42
|
+
loaderKey: "audioSegmentLoaderActor"
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Type-identity bundle for text-track-typed behaviors. Text tracks have
|
|
46
|
+
* no `SourceBufferActor` (MSE doesn't apply), so this bundle omits
|
|
47
|
+
* `actorKey`. The `loaderKey` points at the text-track-segment-loader
|
|
48
|
+
* actor (a `MessageActor` with continue-vs-preempt semantics, parallel
|
|
49
|
+
* to v/a's `SegmentLoaderActor`).
|
|
50
|
+
*
|
|
51
|
+
* @see loadTextTrackSegments, setupTextTrackActors
|
|
52
|
+
*/
|
|
53
|
+
const TEXT_TYPE_CONFIG = {
|
|
54
|
+
type: "text",
|
|
55
|
+
selectedKey: "selectedTextTrackId",
|
|
56
|
+
loaderKey: "textTrackSegmentLoaderActor"
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { AUDIO_TYPE_CONFIG, TEXT_TYPE_CONFIG, VIDEO_TYPE_CONFIG };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=track-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-types.js","names":[],"sources":["../../../../src/playback/behaviors/track-types.ts"],"sourcesContent":["/**\n * **Per-type config bundles for per-type behavior variants.**\n *\n * Each `*_TYPE_CONFIG` constant names the per-type slot keys that\n * per-type-variant setup-shape helpers consume. Variants reference the\n * shared constant at their `defineBehavior` setup body rather than\n * constructing the config inline, so the per-type identity (which state\n * slot, which context slot, which discriminant) lives in one place per\n * type.\n *\n * Variants spread their composition-time `config` over the defaults so\n * engines can layer composition-supplied additions on top (e.g. a\n * custom fetch closure, a non-default segment resolver). Defaults\n * first, engine config second.\n *\n * Helpers continue to consume their slice via the existing typed-key\n * generics (`<K extends SelectedTrackKey>` etc.); the extra fields on\n * the config object (carrying facets other helpers care about) are fine\n * under structural typing.\n */\n\n/**\n * Type-identity bundle for video-track-typed behaviors.\n *\n * @see setupVideoBufferActors, loadVideoSegments\n */\nexport const VIDEO_TYPE_CONFIG = {\n type: 'video',\n selectedKey: 'selectedVideoTrackId',\n actorKey: 'videoBufferActor',\n loaderKey: 'videoSegmentLoaderActor',\n} as const;\n\n/**\n * Type-identity bundle for audio-track-typed behaviors.\n *\n * @see setupAudioBufferActors, loadAudioSegments\n */\nexport const AUDIO_TYPE_CONFIG = {\n type: 'audio',\n selectedKey: 'selectedAudioTrackId',\n actorKey: 'audioBufferActor',\n loaderKey: 'audioSegmentLoaderActor',\n} as const;\n\n/**\n * Type-identity bundle for text-track-typed behaviors. Text tracks have\n * no `SourceBufferActor` (MSE doesn't apply), so this bundle omits\n * `actorKey`. The `loaderKey` points at the text-track-segment-loader\n * actor (a `MessageActor` with continue-vs-preempt semantics, parallel\n * to v/a's `SegmentLoaderActor`).\n *\n * @see loadTextTrackSegments, setupTextTrackActors\n */\nexport const TEXT_TYPE_CONFIG = {\n type: 'text',\n selectedKey: 'selectedTextTrackId',\n loaderKey: 'textTrackSegmentLoaderActor',\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAa,oBAAoB;CAC/B,MAAM;CACN,aAAa;CACb,UAAU;CACV,WAAW;CACZ;;;;;;AAOD,MAAa,oBAAoB;CAC/B,MAAM;CACN,aAAa;CACb,UAAU;CACV,WAAW;CACZ;;;;;;;;;;AAWD,MAAa,mBAAmB;CAC9B,MAAM;CACN,aAAa;CACb,WAAW;CACZ"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { createSimpleHlsEngine } from "./engine.js";
|
|
2
|
+
//#region src/playback/engines/hls/adapter.ts
|
|
3
|
+
const simpleHlsMediaDefaultProps = {
|
|
4
|
+
src: "",
|
|
5
|
+
preload: ""
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* Mixin that adds SPF playback engine behavior to any base class.
|
|
6
9
|
*
|
|
@@ -13,35 +16,36 @@ import { createPlaybackEngine } from "./engine.js";
|
|
|
13
16
|
* changes and re-applied to the new engine automatically.
|
|
14
17
|
*
|
|
15
18
|
* @example
|
|
16
|
-
* class SimpleHlsMedia extends
|
|
19
|
+
* class SimpleHlsMedia extends SimpleHlsMediaMixin(HTMLVideoElementHost) {}
|
|
17
20
|
*
|
|
18
21
|
* const media = new SimpleHlsMedia();
|
|
19
22
|
* media.attach(document.querySelector('video'));
|
|
20
23
|
* media.src = 'https://stream.mux.com/abc123.m3u8';
|
|
21
24
|
*/
|
|
22
|
-
function
|
|
23
|
-
class
|
|
25
|
+
function SimpleHlsMediaMixin(BaseClass) {
|
|
26
|
+
class SimpleHlsMediaImpl extends BaseClass {
|
|
24
27
|
#engine;
|
|
25
28
|
#config;
|
|
26
|
-
#
|
|
29
|
+
#signals;
|
|
30
|
+
#preload = simpleHlsMediaDefaultProps.preload;
|
|
27
31
|
/** Pending loadstart listener from a deferred play() retry, if any. */
|
|
28
32
|
#loadstartListener = null;
|
|
29
33
|
constructor(...args) {
|
|
30
34
|
super(...args);
|
|
31
35
|
const { config } = args?.[0] ?? {};
|
|
32
36
|
this.#config = config;
|
|
33
|
-
this.#engine =
|
|
37
|
+
this.#engine = this.#createEngine();
|
|
34
38
|
}
|
|
35
39
|
get engine() {
|
|
36
40
|
return this.#engine;
|
|
37
41
|
}
|
|
38
42
|
attach(mediaElement) {
|
|
39
43
|
super.attach?.(mediaElement);
|
|
40
|
-
|
|
44
|
+
this.#signals.context.mediaElement.set(mediaElement);
|
|
41
45
|
}
|
|
42
46
|
detach() {
|
|
43
47
|
this.#cancelPendingPlay();
|
|
44
|
-
|
|
48
|
+
this.#signals.context.mediaElement.set(void 0);
|
|
45
49
|
super.detach?.();
|
|
46
50
|
}
|
|
47
51
|
destroy() {
|
|
@@ -53,24 +57,24 @@ function SpfMediaMixin(BaseClass) {
|
|
|
53
57
|
}
|
|
54
58
|
set preload(value) {
|
|
55
59
|
this.#preload = value;
|
|
56
|
-
if (value)
|
|
60
|
+
if (value) this.#signals.state.preload.set(value);
|
|
57
61
|
}
|
|
58
62
|
get src() {
|
|
59
|
-
return this.#
|
|
63
|
+
return this.#signals.state.presentation.get()?.url ?? "";
|
|
60
64
|
}
|
|
61
65
|
set src(value) {
|
|
62
|
-
const prevMediaElement = this.#
|
|
66
|
+
const prevMediaElement = this.#signals.context.mediaElement.get();
|
|
63
67
|
this.#cancelPendingPlay();
|
|
64
68
|
this.#engine.destroy();
|
|
65
|
-
this.#engine =
|
|
66
|
-
if (this.#preload)
|
|
67
|
-
if (prevMediaElement)
|
|
68
|
-
if (value)
|
|
69
|
+
this.#engine = this.#createEngine();
|
|
70
|
+
if (this.#preload) this.#signals.state.preload.set(this.#preload);
|
|
71
|
+
if (prevMediaElement) this.#signals.context.mediaElement.set(prevMediaElement);
|
|
72
|
+
if (value) this.#signals.state.presentation.set({ url: value });
|
|
69
73
|
}
|
|
70
74
|
play() {
|
|
71
|
-
const
|
|
72
|
-
if (!mediaElement) return Promise.reject(/* @__PURE__ */ new Error("
|
|
73
|
-
|
|
75
|
+
const mediaElement = this.#signals.context.mediaElement.get();
|
|
76
|
+
if (!mediaElement) return Promise.reject(/* @__PURE__ */ new Error("SimpleHlsMediaElement: no media element attached"));
|
|
77
|
+
this.#signals.state.loadActivated.set(true);
|
|
74
78
|
return mediaElement.play().catch((err) => {
|
|
75
79
|
if (this.src) return new Promise((resolve, reject) => {
|
|
76
80
|
const listener = () => {
|
|
@@ -83,18 +87,25 @@ function SpfMediaMixin(BaseClass) {
|
|
|
83
87
|
throw err;
|
|
84
88
|
});
|
|
85
89
|
}
|
|
90
|
+
#createEngine() {
|
|
91
|
+
return createSimpleHlsEngine({
|
|
92
|
+
...this.#config,
|
|
93
|
+
onSignalsReady: (signals) => {
|
|
94
|
+
this.#signals = signals;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
86
98
|
#cancelPendingPlay() {
|
|
87
99
|
if (!this.#loadstartListener) return;
|
|
88
|
-
|
|
89
|
-
mediaElement?.removeEventListener("loadstart", this.#loadstartListener);
|
|
100
|
+
this.#signals.context.mediaElement.get()?.removeEventListener("loadstart", this.#loadstartListener);
|
|
90
101
|
this.#loadstartListener = null;
|
|
91
102
|
}
|
|
92
103
|
}
|
|
93
|
-
return
|
|
104
|
+
return SimpleHlsMediaImpl;
|
|
94
105
|
}
|
|
95
106
|
/** Standalone SPF media adapter with no base class. */
|
|
96
|
-
var
|
|
107
|
+
var SimpleHlsMediaElement = class extends SimpleHlsMediaMixin(class {}) {};
|
|
97
108
|
//#endregion
|
|
98
|
-
export {
|
|
109
|
+
export { SimpleHlsMediaElement, SimpleHlsMediaMixin, simpleHlsMediaDefaultProps };
|
|
99
110
|
|
|
100
111
|
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","names":["#config","#engine","#createEngine","#signals","#cancelPendingPlay","#preload","#loadstartListener"],"sources":["../../../../../src/playback/engines/hls/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\nimport type { Composition } from '../../../core/composition/create-composition';\nimport {\n createSimpleHlsEngine,\n type SimpleHlsEngineConfig,\n type SimpleHlsEngineContext,\n type SimpleHlsEngineSignals,\n type SimpleHlsEngineState,\n} from './engine';\n\nexport interface SimpleHlsMediaProps {\n src: string;\n preload: '' | 'none' | 'metadata' | 'auto';\n}\n\nexport const simpleHlsMediaDefaultProps: SimpleHlsMediaProps = {\n src: '',\n preload: '',\n};\n\nexport interface SimpleHlsMediaAPI extends SimpleHlsMediaProps {\n readonly engine: Composition<SimpleHlsEngineState, SimpleHlsEngineContext>;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Mixin that adds SPF playback engine behavior to any base class.\n *\n * Implements the src/play() contract per the WHATWG HTML spec so that SPF can\n * be used anywhere a media element API is expected.\n *\n * A new engine is created on every src assignment — this fully tears down all\n * state, SourceBuffers, and in-flight requests from the previous source before\n * the next one begins. The media element reference is preserved across src\n * changes and re-applied to the new engine automatically.\n *\n * @example\n * class SimpleHlsMedia extends SimpleHlsMediaMixin(HTMLVideoElementHost) {}\n *\n * const media = new SimpleHlsMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/abc123.m3u8';\n */\nexport function SimpleHlsMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class SimpleHlsMediaImpl extends BaseClass {\n #engine: Composition<SimpleHlsEngineState, SimpleHlsEngineContext>;\n #config: SimpleHlsEngineConfig;\n #signals!: SimpleHlsEngineSignals;\n #preload: '' | 'none' | 'metadata' | 'auto' = simpleHlsMediaDefaultProps.preload;\n\n /** Pending loadstart listener from a deferred play() retry, if any. */\n #loadstartListener: (() => void) | null = null;\n\n constructor(...args: any[]) {\n super(...args);\n\n const { config } = args?.[0] ?? {};\n this.#config = config;\n this.#engine = this.#createEngine();\n }\n\n get engine(): Composition<SimpleHlsEngineState, SimpleHlsEngineContext> {\n return this.#engine;\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n this.#signals.context.mediaElement.set(mediaElement);\n }\n\n detach(): void {\n this.#cancelPendingPlay();\n this.#signals.context.mediaElement.set(undefined);\n super.detach?.();\n }\n\n destroy(): void {\n this.#cancelPendingPlay();\n this.#engine.destroy();\n }\n\n // -------------------------------------------------------------------------\n // preload — synchronous IDL attribute (WHATWG §4.8.11.2)\n // -------------------------------------------------------------------------\n\n get preload(): '' | 'none' | 'metadata' | 'auto' {\n return this.#preload;\n }\n\n set preload(value: '' | 'none' | 'metadata' | 'auto') {\n this.#preload = value;\n if (value) {\n this.#signals.state.preload.set(value);\n }\n // value = '' clears #preload (so the next engine recreation won't re-apply\n // an explicit value) but does not patch current state — the existing preload\n // stays in effect until the next src change creates a fresh engine.\n }\n\n // -------------------------------------------------------------------------\n // src — synchronous IDL attribute (WHATWG §4.8.11.2)\n // Each assignment destroys the current engine and starts a fresh one, exactly\n // as the browser's load algorithm resets all media element state on src change.\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#signals.state.presentation.get()?.url ?? '';\n }\n\n set src(value: string) {\n const prevMediaElement = this.#signals.context.mediaElement.get();\n\n this.#cancelPendingPlay();\n this.#engine.destroy();\n this.#engine = this.#createEngine();\n\n // Apply explicit preload before setting context so it's already in\n // state.preload when syncPreload's read effect runs on the attach —\n // the read effect only overwrites when the element's `preload` is a\n // W3C value (which a freshly-created <video> with no attribute is not).\n if (this.#preload) {\n this.#signals.state.preload.set(this.#preload);\n }\n\n if (prevMediaElement) {\n this.#signals.context.mediaElement.set(prevMediaElement);\n }\n\n if (value) {\n this.#signals.state.presentation.set({ url: value });\n }\n }\n\n // -------------------------------------------------------------------------\n // play() — WHATWG §4.8.11.8\n // Delegates to the attached media element's native play().\n // -------------------------------------------------------------------------\n\n play(): Promise<void> {\n const mediaElement = this.#signals.context.mediaElement.get();\n if (!mediaElement) {\n return Promise.reject(new Error('SimpleHlsMediaElement: no media element attached'));\n }\n\n // Signal play intent — enables loading even with preload=\"none\"\n this.#signals.state.loadActivated.set(true);\n\n return mediaElement.play().catch((err: unknown) => {\n // If we have a pending HLS source, the rejection may be because MSE\n // hasn't attached a blob URL yet. Wait for loadstart (src assigned\n // by MSE setup) and retry once.\n if (this.src) {\n return new Promise<void>((resolve, reject) => {\n const listener = () => {\n this.#loadstartListener = null;\n mediaElement.play().then(resolve, reject);\n };\n this.#loadstartListener = listener;\n mediaElement.addEventListener('loadstart', listener, { once: true });\n });\n }\n throw err;\n });\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n #createEngine(): Composition<SimpleHlsEngineState, SimpleHlsEngineContext> {\n return createSimpleHlsEngine({\n ...this.#config,\n onSignalsReady: (signals) => {\n this.#signals = signals;\n },\n });\n }\n\n #cancelPendingPlay(): void {\n if (!this.#loadstartListener) return;\n const mediaElement = this.#signals.context.mediaElement.get();\n mediaElement?.removeEventListener('loadstart', this.#loadstartListener);\n this.#loadstartListener = null;\n }\n }\n\n return SimpleHlsMediaImpl as unknown as MixinReturn<Base, SimpleHlsMediaAPI>;\n}\n\n/** Standalone SPF media adapter with no base class. */\nexport class SimpleHlsMediaElement extends SimpleHlsMediaMixin(class {}) {}\n"],"mappings":";;AAeA,MAAa,6BAAkD;CAC7D,KAAK;CACL,SAAS;CACV;;;;;;;;;;;;;;;;;;;AA4BD,SAAgB,oBAAmD,WAAiB;CAClF,MAAM,2BAA2B,UAAU;EACzC;EACA;EACA;EACA,WAA8C,2BAA2B;;EAGzE,qBAA0C;EAE1C,YAAY,GAAG,MAAa;AAC1B,SAAM,GAAG,KAAK;GAEd,MAAM,EAAE,WAAW,OAAO,MAAM,EAAE;AAClC,SAAA,SAAe;AACf,SAAA,SAAe,MAAA,cAAoB;;EAGrC,IAAI,SAAoE;AACtE,UAAO,MAAA;;EAOT,OAAO,cAAsC;AAC3C,SAAM,SAAS,aAAa;AAC5B,SAAA,QAAc,QAAQ,aAAa,IAAI,aAAa;;EAGtD,SAAe;AACb,SAAA,mBAAyB;AACzB,SAAA,QAAc,QAAQ,aAAa,IAAI,KAAA,EAAU;AACjD,SAAM,UAAU;;EAGlB,UAAgB;AACd,SAAA,mBAAyB;AACzB,SAAA,OAAa,SAAS;;EAOxB,IAAI,UAA6C;AAC/C,UAAO,MAAA;;EAGT,IAAI,QAAQ,OAA0C;AACpD,SAAA,UAAgB;AAChB,OAAI,MACF,OAAA,QAAc,MAAM,QAAQ,IAAI,MAAM;;EAa1C,IAAI,MAAc;AAChB,UAAO,MAAA,QAAc,MAAM,aAAa,KAAK,EAAE,OAAO;;EAGxD,IAAI,IAAI,OAAe;GACrB,MAAM,mBAAmB,MAAA,QAAc,QAAQ,aAAa,KAAK;AAEjE,SAAA,mBAAyB;AACzB,SAAA,OAAa,SAAS;AACtB,SAAA,SAAe,MAAA,cAAoB;AAMnC,OAAI,MAAA,QACF,OAAA,QAAc,MAAM,QAAQ,IAAI,MAAA,QAAc;AAGhD,OAAI,iBACF,OAAA,QAAc,QAAQ,aAAa,IAAI,iBAAiB;AAG1D,OAAI,MACF,OAAA,QAAc,MAAM,aAAa,IAAI,EAAE,KAAK,OAAO,CAAC;;EASxD,OAAsB;GACpB,MAAM,eAAe,MAAA,QAAc,QAAQ,aAAa,KAAK;AAC7D,OAAI,CAAC,aACH,QAAO,QAAQ,uBAAO,IAAI,MAAM,mDAAmD,CAAC;AAItF,SAAA,QAAc,MAAM,cAAc,IAAI,KAAK;AAE3C,UAAO,aAAa,MAAM,CAAC,OAAO,QAAiB;AAIjD,QAAI,KAAK,IACP,QAAO,IAAI,SAAe,SAAS,WAAW;KAC5C,MAAM,iBAAiB;AACrB,YAAA,oBAA0B;AAC1B,mBAAa,MAAM,CAAC,KAAK,SAAS,OAAO;;AAE3C,WAAA,oBAA0B;AAC1B,kBAAa,iBAAiB,aAAa,UAAU,EAAE,MAAM,MAAM,CAAC;MACpE;AAEJ,UAAM;KACN;;EAOJ,gBAA2E;AACzE,UAAO,sBAAsB;IAC3B,GAAG,MAAA;IACH,iBAAiB,YAAY;AAC3B,WAAA,UAAgB;;IAEnB,CAAC;;EAGJ,qBAA2B;AACzB,OAAI,CAAC,MAAA,kBAAyB;AACT,SAAA,QAAc,QAAQ,aAAa,KAAK,EAC/C,oBAAoB,aAAa,MAAA,kBAAwB;AACvE,SAAA,oBAA0B;;;AAI9B,QAAO;;;AAIT,IAAa,wBAAb,cAA2C,oBAAoB,MAAM,GAAG,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createComposition } from "../../../core/composition/create-composition.js";
|
|
2
|
+
import { makeShareSignals } from "../../../core/composition/share-signals.js";
|
|
3
|
+
import { resolveVttSegment } from "../../../media/dom/text/resolve-vtt-segment.js";
|
|
4
|
+
import { loadAudioSegments, loadTextTrackSegments, loadVideoSegments } from "../../behaviors/dom/load-segments.js";
|
|
5
|
+
import { setupTextTrackActors } from "../../behaviors/dom/setup-text-track-actors.js";
|
|
6
|
+
import { trackCurrentTime } from "../../behaviors/dom/track-current-time.js";
|
|
7
|
+
import { trackLoadTriggers } from "../../behaviors/dom/track-load-triggers.js";
|
|
8
|
+
import { addSubtitlesTracksToMedia, getShowingSubtitlesTrackFromMedia, removeAllSubtitlesTracksFromMedia } from "../../../media/dom/text/text-track-slots.js";
|
|
9
|
+
import { parseMultivariantPlaylist } from "../../../media/hls/parse-multivariant.js";
|
|
10
|
+
import { getResolvedSelectedTrackDuration } from "../../../media/utils/track-selection.js";
|
|
11
|
+
import { calculatePresentationDuration } from "../../behaviors/calculate-presentation-duration.js";
|
|
12
|
+
import { endOfStream } from "../../behaviors/dom/end-of-stream.js";
|
|
13
|
+
import { setupAudioBufferActors, setupVideoBufferActors } from "../../behaviors/dom/setup-buffer-actors.js";
|
|
14
|
+
import { setupMediaSource } from "../../behaviors/dom/setup-mediasource.js";
|
|
15
|
+
import { syncTextTracks } from "../../behaviors/dom/sync-text-tracks.js";
|
|
16
|
+
import { updateMediaSourceDuration } from "../../behaviors/dom/update-mediasource-duration.js";
|
|
17
|
+
import { switchVideoQuality } from "../../behaviors/quality-switching.js";
|
|
18
|
+
import { resolvePresentation } from "../../behaviors/resolve-presentation.js";
|
|
19
|
+
import { resolveAudioTrack, resolveTextTrack, resolveVideoTrack } from "../../behaviors/resolve-track.js";
|
|
20
|
+
import { selectAudioTrack, selectTextTrack } from "../../behaviors/select-tracks.js";
|
|
21
|
+
import { syncPreload } from "../../behaviors/sync-preload.js";
|
|
22
|
+
//#region src/playback/engines/hls/engine.ts
|
|
23
|
+
/**
|
|
24
|
+
* Generic `shareSignals` instantiated against the HLS engine's full state
|
|
25
|
+
* and context — captures composition signal refs into the consumer's
|
|
26
|
+
* `onSignalsReady` callback at setup time.
|
|
27
|
+
*/
|
|
28
|
+
const shareSignals = makeShareSignals();
|
|
29
|
+
/**
|
|
30
|
+
* Create an HLS playback engine.
|
|
31
|
+
*
|
|
32
|
+
* Composes SPF behaviors into a reactive pipeline for HLS playback over MSE:
|
|
33
|
+
* manifest resolution, track selection, ABR, segment loading, and
|
|
34
|
+
* end-of-stream coordination.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* let signals: SimpleHlsEngineSignals;
|
|
39
|
+
* const engine = createSimpleHlsEngine({
|
|
40
|
+
* initialBandwidth: 2_000_000,
|
|
41
|
+
* preferredAudioLanguage: 'en',
|
|
42
|
+
* onSignalsReady: (refs) => {
|
|
43
|
+
* signals = refs;
|
|
44
|
+
* },
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* signals.context.mediaElement.set(videoEl);
|
|
48
|
+
* signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });
|
|
49
|
+
*
|
|
50
|
+
* videoEl.play();
|
|
51
|
+
*
|
|
52
|
+
* await engine.destroy();
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
function createSimpleHlsEngine(config = {}) {
|
|
56
|
+
const finalConfig = {
|
|
57
|
+
...config,
|
|
58
|
+
resolveTextTrackSegment: config.resolveTextTrackSegment ?? resolveVttSegment,
|
|
59
|
+
resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,
|
|
60
|
+
parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,
|
|
61
|
+
addSubtitlesTracksToMedia: config.addSubtitlesTracksToMedia ?? addSubtitlesTracksToMedia,
|
|
62
|
+
getShowingSubtitlesTrackFromMedia: config.getShowingSubtitlesTrackFromMedia ?? getShowingSubtitlesTrackFromMedia,
|
|
63
|
+
removeAllSubtitlesTracksFromMedia: config.removeAllSubtitlesTracksFromMedia ?? removeAllSubtitlesTracksFromMedia
|
|
64
|
+
};
|
|
65
|
+
return createComposition([
|
|
66
|
+
syncPreload,
|
|
67
|
+
trackLoadTriggers,
|
|
68
|
+
resolvePresentation,
|
|
69
|
+
selectAudioTrack,
|
|
70
|
+
selectTextTrack,
|
|
71
|
+
resolveVideoTrack,
|
|
72
|
+
resolveAudioTrack,
|
|
73
|
+
resolveTextTrack,
|
|
74
|
+
calculatePresentationDuration,
|
|
75
|
+
setupMediaSource,
|
|
76
|
+
updateMediaSourceDuration,
|
|
77
|
+
setupVideoBufferActors,
|
|
78
|
+
setupAudioBufferActors,
|
|
79
|
+
trackCurrentTime,
|
|
80
|
+
switchVideoQuality,
|
|
81
|
+
loadVideoSegments,
|
|
82
|
+
loadAudioSegments,
|
|
83
|
+
endOfStream,
|
|
84
|
+
syncTextTracks,
|
|
85
|
+
setupTextTrackActors,
|
|
86
|
+
loadTextTrackSegments,
|
|
87
|
+
shareSignals
|
|
88
|
+
], {
|
|
89
|
+
config: finalConfig,
|
|
90
|
+
initialState: { bandwidthState: {
|
|
91
|
+
fastEstimate: 0,
|
|
92
|
+
fastTotalWeight: 0,
|
|
93
|
+
slowEstimate: 0,
|
|
94
|
+
slowTotalWeight: 0,
|
|
95
|
+
bytesSampled: 0
|
|
96
|
+
} }
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { createSimpleHlsEngine };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","names":[],"sources":["../../../../../src/playback/engines/hls/engine.ts"],"sourcesContent":["import {\n type Composition,\n type ContextSignals,\n createComposition,\n type StateSignals,\n} from '../../../core/composition/create-composition';\nimport { makeShareSignals, type ShareSignalsConfig } from '../../../core/composition/share-signals';\nimport type { QualityConfig } from '../../../media/abr/quality-selection';\nimport type { BackBufferConfig } from '../../../media/buffer/back-buffer';\nimport type { ForwardBufferConfig } from '../../../media/buffer/forward-buffer';\nimport { resolveVttSegment } from '../../../media/dom/text/resolve-vtt-segment';\nimport {\n addSubtitlesTracksToMedia,\n getShowingSubtitlesTrackFromMedia,\n removeAllSubtitlesTracksFromMedia,\n} from '../../../media/dom/text/text-track-slots';\nimport { parseMultivariantPlaylist } from '../../../media/hls/parse-multivariant';\nimport type { MaybeResolvedPresentation, VideoTrack } from '../../../media/types';\nimport { getResolvedSelectedTrackDuration } from '../../../media/utils/track-selection';\nimport type { BandwidthConfig, BandwidthState } from '../../../network/bandwidth-estimator';\nimport type { SegmentLoaderActor } from '../../actors/dom/segment-loader';\nimport type { SourceBufferActor } from '../../actors/dom/source-buffer';\nimport type { TextTracksActor } from '../../actors/dom/text-tracks';\nimport type { TextTrackSegmentLoaderActor, TextTrackSegmentResolver } from '../../actors/text-track-segment-loader';\nimport {\n calculatePresentationDuration,\n type PresentationDurationResolver,\n} from '../../behaviors/calculate-presentation-duration';\nimport { endOfStream } from '../../behaviors/dom/end-of-stream';\nimport { loadAudioSegments, loadTextTrackSegments, loadVideoSegments } from '../../behaviors/dom/load-segments';\nimport { setupAudioBufferActors, setupVideoBufferActors } from '../../behaviors/dom/setup-buffer-actors';\nimport { setupMediaSource } from '../../behaviors/dom/setup-mediasource';\nimport { setupTextTrackActors } from '../../behaviors/dom/setup-text-track-actors';\nimport { syncTextTracks } from '../../behaviors/dom/sync-text-tracks';\nimport { trackCurrentTime } from '../../behaviors/dom/track-current-time';\nimport { trackLoadTriggers } from '../../behaviors/dom/track-load-triggers';\nimport { updateMediaSourceDuration } from '../../behaviors/dom/update-mediasource-duration';\nimport { switchVideoQuality } from '../../behaviors/quality-switching';\nimport { type ParsePresentation, resolvePresentation } from '../../behaviors/resolve-presentation';\nimport { resolveAudioTrack, resolveTextTrack, resolveVideoTrack } from '../../behaviors/resolve-track';\nimport { selectAudioTrack, selectTextTrack } from '../../behaviors/select-tracks';\nimport { syncPreload } from '../../behaviors/sync-preload';\n\n// ============================================================================\n// HLS Engine State & Context\n// ============================================================================\n\n/**\n * State shape for the HLS playback engine.\n *\n * This is the union of all state required by the behaviors composed into\n * the HLS engine. Each behavior declares its own state interface; this\n * type satisfies all of them.\n */\nexport interface SimpleHlsEngineState {\n /**\n * The presentation being played. A caller writes `{ url }`;\n * `resolvePresentation` parses the manifest and populates the rest.\n */\n presentation?: MaybeResolvedPresentation;\n preload?: 'auto' | 'metadata' | 'none';\n selectedVideoTrackId?: string;\n selectedAudioTrackId?: string;\n selectedTextTrackId?: string;\n bandwidthState?: BandwidthState;\n userVideoTrackSelection?: Partial<VideoTrack>;\n currentTime?: number;\n loadActivated?: boolean;\n}\n\n/**\n * Context shape for the HLS playback engine.\n *\n * Platform objects and actor references managed by HLS behaviors.\n */\nexport interface SimpleHlsEngineContext {\n mediaElement?: HTMLMediaElement | undefined;\n mediaSource?: MediaSource;\n videoBufferActor?: SourceBufferActor;\n audioBufferActor?: SourceBufferActor;\n videoSegmentLoaderActor?: SegmentLoaderActor;\n audioSegmentLoaderActor?: SegmentLoaderActor;\n textTracksActor?: TextTracksActor;\n textTrackSegmentLoaderActor?: TextTrackSegmentLoaderActor;\n}\n\n/**\n * The composition signal refs handed to `onSignalsReady` callers — the\n * canonical way to drive the engine externally (writes) or observe its\n * state (reads) without touching `composition.state` / `composition.context`\n * directly.\n */\nexport type SimpleHlsEngineSignals = {\n state: StateSignals<SimpleHlsEngineState>;\n context: ContextSignals<SimpleHlsEngineContext>;\n};\n\n/**\n * Configuration for the HLS playback engine.\n *\n * Each option is consumed by the appropriate behavior — the engine itself\n * has no config beyond what its behaviors read.\n */\nexport interface SimpleHlsEngineConfig extends ShareSignalsConfig<SimpleHlsEngineState, SimpleHlsEngineContext> {\n /**\n * Bandwidth estimate in bps to use before enough samples have been\n * collected. Default: `DEFAULT_INITIAL_BANDWIDTH` (5 Mbps).\n */\n initialBandwidth?: number;\n preferredAudioLanguage?: string;\n preferredSubtitleLanguage?: string;\n includeForcedTracks?: boolean;\n enableDefaultTrack?: boolean;\n /**\n * Resolver that turns a text-track segment fetch into VTT cues.\n * Defaults to the DOM-bound `resolveVttSegment` resolver, which uses an\n * offscreen `<track>` element to parse WebVTT.\n */\n resolveTextTrackSegment?: TextTrackSegmentResolver<VTTCue>;\n /**\n * Resolver for `presentation.duration`. Defaults to picking the first\n * resolved selected track's duration (video preferred, audio fallback) —\n * appropriate for VoD and audio-only. Live engines should supply a\n * resolver that returns `Number.POSITIVE_INFINITY` once the presentation\n * is established as live; downstream `updateMediaSourceDuration` propagates\n * that value to `mediaSource.duration` per the MSE spec.\n */\n resolveDuration?: PresentationDurationResolver;\n /**\n * Manifest parser handed to `resolvePresentation`. Defaults to the HLS\n * multivariant-playlist parser; supply your own for alternate format\n * support without forking the engine.\n */\n parsePresentation?: ParsePresentation;\n /**\n * Allocate SPF-owned text-track slots on the media element. Defaults to\n * the standard `<track>`-element implementation in\n * `media/dom/text/text-track-slots`.\n */\n addSubtitlesTracksToMedia?: typeof addSubtitlesTracksToMedia;\n /**\n * Return the SPF-owned subtitle/caption `TextTrack` currently in showing\n * mode. Defaults to the standard selector-based implementation in\n * `media/dom/text/text-track-slots`.\n */\n getShowingSubtitlesTrackFromMedia?: typeof getShowingSubtitlesTrackFromMedia;\n /**\n * Evict all SPF-owned text-track slots from the media element. Defaults to\n * the standard selector-based implementation in\n * `media/dom/text/text-track-slots`.\n */\n removeAllSubtitlesTracksFromMedia?: typeof removeAllSubtitlesTracksFromMedia;\n /**\n * Forward-buffer tuning. `bufferDuration` controls how far ahead of the\n * playhead segments are loaded (and where forward-flush kicks in).\n * Defaults: see `DEFAULT_FORWARD_BUFFER_CONFIG` (30 seconds). Threaded to\n * segment-loader actors (v/a + text) at construction time and to\n * `loadXSegments` dispatchers for the load-message range.\n */\n forwardBuffer?: Partial<ForwardBufferConfig>;\n /**\n * Back-buffer tuning. `keepSegments` controls how many segments stay\n * behind the playhead before eviction. Defaults: see\n * `DEFAULT_BACK_BUFFER_CONFIG` (2 segments). Threaded to the v/a\n * segment-loader actor only (text tracks don't use back-buffer eviction).\n */\n backBuffer?: Partial<BackBufferConfig>;\n /**\n * Bandwidth-estimator tuning. Overrides any field of `BandwidthConfig`\n * (`fastHalfLife`, `slowHalfLife`, `minTotalBytes`, `minBytes`,\n * `minDuration`). `bandwidth.minTotalBytes` supersedes the flat\n * `minTotalBytes` field above. Defaults: see `DEFAULT_BANDWIDTH_CONFIG`.\n */\n bandwidth?: Partial<BandwidthConfig>;\n /**\n * Quality-selection tuning. `safetyMargin` is the bandwidth-headroom\n * multiplier used by `selectQuality`; `upgradeMargin` is the hysteresis\n * ratio gating ABR upgrades. Defaults: `DEFAULT_QUALITY_CONFIG` (0.85 / 1.15).\n */\n quality?: Partial<QualityConfig>;\n}\n\n// ============================================================================\n// HLS Playback Engine\n// ============================================================================\n\n/**\n * Generic `shareSignals` instantiated against the HLS engine's full state\n * and context — captures composition signal refs into the consumer's\n * `onSignalsReady` callback at setup time.\n */\nconst shareSignals = makeShareSignals<SimpleHlsEngineState, SimpleHlsEngineContext>();\n\n/**\n * Create an HLS playback engine.\n *\n * Composes SPF behaviors into a reactive pipeline for HLS playback over MSE:\n * manifest resolution, track selection, ABR, segment loading, and\n * end-of-stream coordination.\n *\n * @example\n * ```ts\n * let signals: SimpleHlsEngineSignals;\n * const engine = createSimpleHlsEngine({\n * initialBandwidth: 2_000_000,\n * preferredAudioLanguage: 'en',\n * onSignalsReady: (refs) => {\n * signals = refs;\n * },\n * });\n *\n * signals.context.mediaElement.set(videoEl);\n * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });\n *\n * videoEl.play();\n *\n * await engine.destroy();\n * ```\n */\nexport function createSimpleHlsEngine(\n config: SimpleHlsEngineConfig = {}\n): Composition<SimpleHlsEngineState, SimpleHlsEngineContext> {\n const finalConfig = {\n ...config,\n resolveTextTrackSegment: config.resolveTextTrackSegment ?? resolveVttSegment,\n resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,\n parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,\n addSubtitlesTracksToMedia: config.addSubtitlesTracksToMedia ?? addSubtitlesTracksToMedia,\n getShowingSubtitlesTrackFromMedia: config.getShowingSubtitlesTrackFromMedia ?? getShowingSubtitlesTrackFromMedia,\n removeAllSubtitlesTracksFromMedia: config.removeAllSubtitlesTracksFromMedia ?? removeAllSubtitlesTracksFromMedia,\n };\n\n return createComposition(\n [\n syncPreload,\n trackLoadTriggers,\n resolvePresentation,\n\n // Track selection (reads config for initial preferences).\n // Video selection lives in switchVideoQuality, which owns the\n // default-pick + ABR-driven adjustment for selectedVideoTrackId.\n selectAudioTrack,\n selectTextTrack,\n\n // Resolve selected tracks (fetch media playlists)\n resolveVideoTrack,\n resolveAudioTrack,\n resolveTextTrack,\n\n // Presentation duration\n calculatePresentationDuration,\n\n // MSE setup. Video cluster is registered first so that, when both\n // per-type variants flip to `'buffer-ready'` on the shared gate's\n // monitor evaluation, `addSourceBuffer(video)` runs before\n // `addSourceBuffer(audio)` — see the Firefox `mozHasAudio` invariant\n // in setup-buffer-actors.ts.\n setupMediaSource,\n updateMediaSourceDuration,\n setupVideoBufferActors,\n setupAudioBufferActors,\n\n // Playback tracking\n trackCurrentTime,\n switchVideoQuality,\n\n // Segment loading\n loadVideoSegments,\n loadAudioSegments,\n\n // End of stream coordination\n endOfStream,\n\n // Text tracks\n syncTextTracks,\n setupTextTrackActors,\n loadTextTrackSegments,\n\n // Behavior whose sole purpose is to use a callback to allow for signal writing from the outside (e.g. an adapter)\n // NOTE: While not required, adding at the end since behaviors are setup in order, so this increases the likelihood\n // that initial signal setup will have occurred before shareSignals' callback is invoked. (CJP)\n shareSignals,\n ],\n {\n config: finalConfig,\n // Seed bandwidthState so switchVideoQuality fires on initial subscribe\n // with the `initialBandwidth` fallback rather than waiting for the\n // first chunk. The empty sample buffer means `getBandwidthEstimate`\n // returns the configured initial bandwidth until real samples land.\n initialState: {\n bandwidthState: {\n fastEstimate: 0,\n fastTotalWeight: 0,\n slowEstimate: 0,\n slowTotalWeight: 0,\n bytesSampled: 0,\n },\n },\n }\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA+LA,MAAM,eAAe,kBAAgE;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BrF,SAAgB,sBACd,SAAgC,EAAE,EACyB;CAC3D,MAAM,cAAc;EAClB,GAAG;EACH,yBAAyB,OAAO,2BAA2B;EAC3D,iBAAiB,OAAO,mBAAmB;EAC3C,mBAAmB,OAAO,qBAAqB;EAC/C,2BAA2B,OAAO,6BAA6B;EAC/D,mCAAmC,OAAO,qCAAqC;EAC/E,mCAAmC,OAAO,qCAAqC;EAChF;AAED,QAAO,kBACL;EACE;EACA;EACA;EAKA;EACA;EAGA;EACA;EACA;EAGA;EAOA;EACA;EACA;EACA;EAGA;EACA;EAGA;EACA;EAGA;EAGA;EACA;EACA;EAKA;EACD,EACD;EACE,QAAQ;EAKR,cAAc,EACZ,gBAAgB;GACd,cAAc;GACd,iBAAiB;GACjB,cAAc;GACd,iBAAiB;GACjB,cAAc;GACf,EACF;EACF,CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Machine, MachineSnapshot } from "
|
|
1
|
+
import { Machine, MachineSnapshot } from "../machine.js";
|
|
2
2
|
|
|
3
|
-
//#region src/core/actor.d.ts
|
|
3
|
+
//#region src/core/actors/actor.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Complete actor snapshot: finite state + non-finite context.
|
|
6
6
|
* Extends `MachineSnapshot` with context — the non-finite data managed by the actor.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor.d.ts","names":[],"sources":["../../../../src/core/actors/actor.ts"],"mappings":";;;;;;;UAeiB,aAAA,uDAAoE,eAAA,CAAgB,KAAA;EACnG,OAAA,EAAS,OAAA;AAAA;;UAIM,WAAA,uDACP,OAAA,CAAQ,aAAA,CAAc,KAAA,EAAO,OAAA;AADvC;;;;;;AAAA,UASiB,aAAA;EAAgC,IAAA;AAAA;EAC/C,IAAA,CAAK,OAAA,EAAS,OAAA;EACd,OAAA;AAAA"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { TaskLike } from "../tasks/task.js";
|
|
2
|
+
import { SignalActor } from "./actor.js";
|
|
3
|
+
|
|
4
|
+
//#region src/core/actors/create-machine-actor.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Minimal interface for any runner that can be used with createMachineActor.
|
|
7
|
+
*/
|
|
8
|
+
interface RunnerLike {
|
|
9
|
+
schedule<Value = void, Err = unknown>(task: TaskLike<Value, Err>): Promise<Value>;
|
|
10
|
+
abortAll(): void;
|
|
11
|
+
destroy(): void;
|
|
12
|
+
whenSettled(callback: () => void): void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Context passed to message handlers.
|
|
16
|
+
* `runner` is present and typed as the exact runner instance only when the
|
|
17
|
+
* definition includes a runner factory.
|
|
18
|
+
*/
|
|
19
|
+
type HandlerContext<UserState extends string, Context extends object, RunnerFactory extends (() => RunnerLike) | undefined> = {
|
|
20
|
+
transition: (to: UserState) => void; /** Context snapshot captured at dispatch time. Stale after any `setContext` call. */
|
|
21
|
+
context: Context;
|
|
22
|
+
/**
|
|
23
|
+
* Live untracked read of the current context. Use in async task closures that
|
|
24
|
+
* execute after the handler returns — e.g. `getCtx: getContext` passed to tasks
|
|
25
|
+
* scheduled on the runner, so each task reads the context committed by the
|
|
26
|
+
* previous task rather than the stale snapshot from dispatch time.
|
|
27
|
+
*/
|
|
28
|
+
getContext: () => Context;
|
|
29
|
+
setContext: (next: Context) => void;
|
|
30
|
+
} & (RunnerFactory extends (() => infer R) ? {
|
|
31
|
+
runner: R;
|
|
32
|
+
} : object);
|
|
33
|
+
/**
|
|
34
|
+
* Definition for a single user-defined state.
|
|
35
|
+
*/
|
|
36
|
+
type ActorStateDefinition<UserState extends string, Context extends object, Message extends {
|
|
37
|
+
type: string;
|
|
38
|
+
}, RunnerFactory extends (() => RunnerLike) | undefined> = {
|
|
39
|
+
/**
|
|
40
|
+
* When the actor's runner settles while in this state, automatically
|
|
41
|
+
* transition to this state. The framework owns the generation-token logic —
|
|
42
|
+
* re-registering after each `runner.schedule()` call so that
|
|
43
|
+
* `abortAll()` + reschedule correctly supersedes stale callbacks.
|
|
44
|
+
*/
|
|
45
|
+
onSettled?: UserState; /** Message handlers active in this state. Messages with no handler are silently dropped. */
|
|
46
|
+
on?: { [M in Message as M['type']]?: (message: Extract<Message, {
|
|
47
|
+
type: M['type'];
|
|
48
|
+
}>, ctx: HandlerContext<UserState, Context, RunnerFactory>) => void };
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Full actor definition passed to `createMachineActor`.
|
|
52
|
+
*
|
|
53
|
+
* `UserState` is the set of domain-meaningful states. `'destroyed'` is always
|
|
54
|
+
* added by the framework as the implicit terminal state — do not include it here.
|
|
55
|
+
*/
|
|
56
|
+
type ActorDefinition<UserState extends string, Context extends object, Message extends {
|
|
57
|
+
type: string;
|
|
58
|
+
}, RunnerFactory extends (() => RunnerLike) | undefined = undefined> = {
|
|
59
|
+
/**
|
|
60
|
+
* Runner factory — called once at `createMachineActor()` time.
|
|
61
|
+
* The runner lives for the full actor lifetime and is destroyed with it.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* runner: () => new SerialRunner()
|
|
65
|
+
*/
|
|
66
|
+
runner?: RunnerFactory; /** Initial state. */
|
|
67
|
+
initial: UserState; /** Initial context. */
|
|
68
|
+
context: Context;
|
|
69
|
+
/**
|
|
70
|
+
* Per-state definitions. States with no definition silently drop all messages.
|
|
71
|
+
* All user-defined states must appear as keys in the `UserState` union.
|
|
72
|
+
*/
|
|
73
|
+
states: Partial<Record<UserState, ActorStateDefinition<UserState, Context, Message, RunnerFactory>>>;
|
|
74
|
+
};
|
|
75
|
+
/** Live actor instance returned by `createMachineActor`. */
|
|
76
|
+
interface MessageActor<State extends string, Context extends object, Message extends {
|
|
77
|
+
type: string;
|
|
78
|
+
}> extends SignalActor<State, Context> {
|
|
79
|
+
send(message: Message): void;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a message-driven actor from a declarative definition.
|
|
83
|
+
*
|
|
84
|
+
* The actor owns a reactive snapshot signal (state + context), an optional
|
|
85
|
+
* runner, and dispatches incoming messages to per-state handlers. `'destroyed'`
|
|
86
|
+
* is always the implicit terminal state — `destroy()` transitions there
|
|
87
|
+
* unconditionally and all subsequent `send()` calls are no-ops.
|
|
88
|
+
*
|
|
89
|
+
* When a state declares `onSettled`, the framework calls `runner.whenSettled()`
|
|
90
|
+
* after the handler returns. The runner owns the generation-token logic — if
|
|
91
|
+
* new tasks are scheduled before the current batch settles, the callback is
|
|
92
|
+
* automatically superseded.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* const actor = createMachineActor({
|
|
96
|
+
* runner: () => new SerialRunner(),
|
|
97
|
+
* initial: 'idle',
|
|
98
|
+
* context: {},
|
|
99
|
+
* states: {
|
|
100
|
+
* idle: {
|
|
101
|
+
* on: {
|
|
102
|
+
* load: (msg, { transition, runner }) => {
|
|
103
|
+
* segments.forEach(s => runner.schedule(new Task(...)));
|
|
104
|
+
* transition('loading');
|
|
105
|
+
* }
|
|
106
|
+
* }
|
|
107
|
+
* },
|
|
108
|
+
* loading: {
|
|
109
|
+
* onSettled: 'idle',
|
|
110
|
+
* on: {
|
|
111
|
+
* load: (msg, { runner }) => {
|
|
112
|
+
* runner.abortAll();
|
|
113
|
+
* segments.forEach(s => runner.schedule(new Task(...)));
|
|
114
|
+
* }
|
|
115
|
+
* }
|
|
116
|
+
* }
|
|
117
|
+
* }
|
|
118
|
+
* });
|
|
119
|
+
*/
|
|
120
|
+
declare function createMachineActor<UserState extends string, Context extends object, Message extends {
|
|
121
|
+
type: string;
|
|
122
|
+
}, RunnerFactory extends (() => RunnerLike) | undefined = undefined>(def: ActorDefinition<UserState, Context, Message, RunnerFactory>): MessageActor<UserState | 'destroyed', Context, Message>;
|
|
123
|
+
//#endregion
|
|
124
|
+
export { ActorDefinition, ActorStateDefinition, HandlerContext, MessageActor, RunnerLike, createMachineActor };
|
|
125
|
+
//# sourceMappingURL=create-machine-actor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-machine-actor.d.ts","names":[],"sources":["../../../../src/core/actors/create-machine-actor.ts"],"mappings":";;;;;;AAYA;UAAiB,UAAA;EACf,QAAA,8BAAsC,IAAA,EAAM,QAAA,CAAS,KAAA,EAAO,GAAA,IAAO,OAAA,CAAQ,KAAA;EAC3E,QAAA;EACA,OAAA;EACA,WAAA,CAAY,QAAA;AAAA;;;;;;KAYF,cAAA,gFAGmB,UAAA;EAE7B,UAAA,GAAa,EAAA,EAAI,SAAA,WApBoC;EAsBrD,OAAA,EAAS,OAAA;EAtB6B;;;;;;EA6BtC,UAAA,QAAkB,OAAA;EAClB,UAAA,GAAa,IAAA,EAAM,OAAA;AAAA,KAChB,aAAA;EAAwC,MAAA,EAAQ,CAAA;AAAA;;;;KAKzC,oBAAA;EAGQ,IAAA;AAAA,gCACW,UAAA;EAT1B;;;;;;EAiBH,SAAA,GAAY,SAAA,EA9BiB;EAgC7B,EAAA,WACQ,OAAA,IAAW,CAAA,aACf,OAAA,EAAS,OAAA,CAAQ,OAAA;IAAW,IAAA,EAAM,CAAA;EAAA,IAClC,GAAA,EAAK,cAAA,CAAe,SAAA,EAAW,OAAA,EAAS,aAAA;AAAA;;;;;;;KAWlC,eAAA;EAGQ,IAAA;AAAA,gCACW,UAAA;EArCuB;AAKtD;;;;;;EAyCE,MAAA,GAAS,aAAA,EAzBY;EA2BrB,OAAA,EAAS,SAAA,EA3BI;EA6Bb,OAAA,EAAS,OAAA;EA5B0B;;;;EAiCnC,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,SAAA,EAAW,oBAAA,CAAqB,SAAA,EAAW,OAAA,EAAS,OAAA,EAAS,aAAA;AAAA;;UAQrE,YAAA;EAA6E,IAAA;AAAA,WACpF,WAAA,CAAY,KAAA,EAAO,OAAA;EAC3B,IAAA,CAAK,OAAA,EAAS,OAAA;AAAA;;;;;;;;;;;;;;;;;;AAhChB;;;;;;;;;;;;;;;;;;;;;;iBA8EgB,kBAAA;EAGI,IAAA;AAAA,gCACW,UAAA,0BAAA,CAE7B,GAAA,EAAK,eAAA,CAAgB,SAAA,EAAW,OAAA,EAAS,OAAA,EAAS,aAAA,IACjD,YAAA,CAAa,SAAA,gBAAyB,OAAA,EAAS,OAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { untrack, update } from "
|
|
2
|
-
import { createMachineCore } from "
|
|
3
|
-
//#region src/core/create-machine-actor.ts
|
|
1
|
+
import { untrack, update } from "../signals/primitives.js";
|
|
2
|
+
import { createMachineCore } from "../machine.js";
|
|
3
|
+
//#region src/core/actors/create-machine-actor.ts
|
|
4
4
|
/**
|
|
5
5
|
* Creates a message-driven actor from a declarative definition.
|
|
6
6
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-machine-actor.js","names":[],"sources":["../../../../src/core/actors/create-machine-actor.ts"],"sourcesContent":["import { createMachineCore } from '../machine';\nimport { untrack, update } from '../signals/primitives';\nimport type { TaskLike } from '../tasks/task';\nimport type { ActorSnapshot, SignalActor } from './actor';\n\n// =============================================================================\n// Runner interfaces\n// =============================================================================\n\n/**\n * Minimal interface for any runner that can be used with createMachineActor.\n */\nexport interface RunnerLike {\n schedule<Value = void, Err = unknown>(task: TaskLike<Value, Err>): Promise<Value>;\n abortAll(): void;\n destroy(): void;\n whenSettled(callback: () => void): void;\n}\n\n// =============================================================================\n// Definition types\n// =============================================================================\n\n/**\n * Context passed to message handlers.\n * `runner` is present and typed as the exact runner instance only when the\n * definition includes a runner factory.\n */\nexport type HandlerContext<\n UserState extends string,\n Context extends object,\n RunnerFactory extends (() => RunnerLike) | undefined,\n> = {\n transition: (to: UserState) => void;\n /** Context snapshot captured at dispatch time. Stale after any `setContext` call. */\n context: Context;\n /**\n * Live untracked read of the current context. Use in async task closures that\n * execute after the handler returns — e.g. `getCtx: getContext` passed to tasks\n * scheduled on the runner, so each task reads the context committed by the\n * previous task rather than the stale snapshot from dispatch time.\n */\n getContext: () => Context;\n setContext: (next: Context) => void;\n} & (RunnerFactory extends () => infer R ? { runner: R } : object);\n\n/**\n * Definition for a single user-defined state.\n */\nexport type ActorStateDefinition<\n UserState extends string,\n Context extends object,\n Message extends { type: string },\n RunnerFactory extends (() => RunnerLike) | undefined,\n> = {\n /**\n * When the actor's runner settles while in this state, automatically\n * transition to this state. The framework owns the generation-token logic —\n * re-registering after each `runner.schedule()` call so that\n * `abortAll()` + reschedule correctly supersedes stale callbacks.\n */\n onSettled?: UserState;\n /** Message handlers active in this state. Messages with no handler are silently dropped. */\n on?: {\n [M in Message as M['type']]?: (\n message: Extract<Message, { type: M['type'] }>,\n ctx: HandlerContext<UserState, Context, RunnerFactory>\n ) => void;\n };\n};\n\n/**\n * Full actor definition passed to `createMachineActor`.\n *\n * `UserState` is the set of domain-meaningful states. `'destroyed'` is always\n * added by the framework as the implicit terminal state — do not include it here.\n */\nexport type ActorDefinition<\n UserState extends string,\n Context extends object,\n Message extends { type: string },\n RunnerFactory extends (() => RunnerLike) | undefined = undefined,\n> = {\n /**\n * Runner factory — called once at `createMachineActor()` time.\n * The runner lives for the full actor lifetime and is destroyed with it.\n *\n * @example\n * runner: () => new SerialRunner()\n */\n runner?: RunnerFactory;\n /** Initial state. */\n initial: UserState;\n /** Initial context. */\n context: Context;\n /**\n * Per-state definitions. States with no definition silently drop all messages.\n * All user-defined states must appear as keys in the `UserState` union.\n */\n states: Partial<Record<UserState, ActorStateDefinition<UserState, Context, Message, RunnerFactory>>>;\n};\n\n// =============================================================================\n// Live actor interface\n// =============================================================================\n\n/** Live actor instance returned by `createMachineActor`. */\nexport interface MessageActor<State extends string, Context extends object, Message extends { type: string }>\n extends SignalActor<State, Context> {\n send(message: Message): void;\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\n/**\n * Creates a message-driven actor from a declarative definition.\n *\n * The actor owns a reactive snapshot signal (state + context), an optional\n * runner, and dispatches incoming messages to per-state handlers. `'destroyed'`\n * is always the implicit terminal state — `destroy()` transitions there\n * unconditionally and all subsequent `send()` calls are no-ops.\n *\n * When a state declares `onSettled`, the framework calls `runner.whenSettled()`\n * after the handler returns. The runner owns the generation-token logic — if\n * new tasks are scheduled before the current batch settles, the callback is\n * automatically superseded.\n *\n * @example\n * const actor = createMachineActor({\n * runner: () => new SerialRunner(),\n * initial: 'idle',\n * context: {},\n * states: {\n * idle: {\n * on: {\n * load: (msg, { transition, runner }) => {\n * segments.forEach(s => runner.schedule(new Task(...)));\n * transition('loading');\n * }\n * }\n * },\n * loading: {\n * onSettled: 'idle',\n * on: {\n * load: (msg, { runner }) => {\n * runner.abortAll();\n * segments.forEach(s => runner.schedule(new Task(...)));\n * }\n * }\n * }\n * }\n * });\n */\nexport function createMachineActor<\n UserState extends string,\n Context extends object,\n Message extends { type: string },\n RunnerFactory extends (() => RunnerLike) | undefined = undefined,\n>(\n def: ActorDefinition<UserState, Context, Message, RunnerFactory>\n): MessageActor<UserState | 'destroyed', Context, Message> {\n type FullState = UserState | 'destroyed';\n\n const runner = def.runner?.() as RunnerLike | undefined;\n const { snapshotSignal, getState, transition } = createMachineCore<FullState, ActorSnapshot<FullState, Context>>({\n value: def.initial as FullState,\n context: def.context,\n });\n\n const getContext = (): Context => untrack(() => snapshotSignal.get().context);\n\n const setContext = (context: Context): void => {\n update(snapshotSignal, { context });\n };\n\n return {\n get snapshot() {\n return snapshotSignal;\n },\n\n send(message: Message): void {\n const state = getState();\n if (state === 'destroyed') return;\n const stateDef = def.states[state as UserState];\n const handler = stateDef?.on?.[message.type as keyof typeof stateDef.on] as\n | ((msg: Message, ctx: HandlerContext<UserState, Context, RunnerFactory>) => void)\n | undefined;\n if (!handler) return;\n handler(message, {\n context: getContext(),\n getContext,\n transition: (to: UserState) => transition(to as FullState),\n setContext,\n ...(runner ? { runner } : {}),\n } as HandlerContext<UserState, Context, RunnerFactory>);\n // Register onSettled after the handler so we read the post-transition state.\n const newState = getState();\n if (newState !== 'destroyed') {\n const newStateDef = def.states[newState as UserState];\n if (newStateDef?.onSettled && runner) {\n const targetState = newStateDef.onSettled as FullState;\n runner.whenSettled(() => {\n if (getState() !== newState) return;\n transition(targetState);\n });\n }\n }\n },\n\n destroy(): void {\n if (getState() === 'destroyed') return;\n runner?.destroy();\n transition('destroyed');\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JA,SAAgB,mBAMd,KACyD;CAGzD,MAAM,SAAS,IAAI,UAAU;CAC7B,MAAM,EAAE,gBAAgB,UAAU,eAAe,kBAAgE;EAC/G,OAAO,IAAI;EACX,SAAS,IAAI;EACd,CAAC;CAEF,MAAM,mBAA4B,cAAc,eAAe,KAAK,CAAC,QAAQ;CAE7E,MAAM,cAAc,YAA2B;AAC7C,SAAO,gBAAgB,EAAE,SAAS,CAAC;;AAGrC,QAAO;EACL,IAAI,WAAW;AACb,UAAO;;EAGT,KAAK,SAAwB;GAC3B,MAAM,QAAQ,UAAU;AACxB,OAAI,UAAU,YAAa;GAE3B,MAAM,UADW,IAAI,OAAO,QACF,KAAK,QAAQ;AAGvC,OAAI,CAAC,QAAS;AACd,WAAQ,SAAS;IACf,SAAS,YAAY;IACrB;IACA,aAAa,OAAkB,WAAW,GAAgB;IAC1D;IACA,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;IAC7B,CAAsD;GAEvD,MAAM,WAAW,UAAU;AAC3B,OAAI,aAAa,aAAa;IAC5B,MAAM,cAAc,IAAI,OAAO;AAC/B,QAAI,aAAa,aAAa,QAAQ;KACpC,MAAM,cAAc,YAAY;AAChC,YAAO,kBAAkB;AACvB,UAAI,UAAU,KAAK,SAAU;AAC7B,iBAAW,YAAY;OACvB;;;;EAKR,UAAgB;AACd,OAAI,UAAU,KAAK,YAAa;AAChC,WAAQ,SAAS;AACjB,cAAW,YAAY;;EAE1B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ActorSnapshot } from "./actor.js";
|
|
2
|
+
import { Machine } from "../machine.js";
|
|
3
|
+
|
|
4
|
+
//#region src/core/actors/create-transition-actor.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A reducer-shaped actor: `(context, message) => context`.
|
|
7
|
+
*
|
|
8
|
+
* No finite states — the snapshot carries `value: 'active' | 'destroyed'`
|
|
9
|
+
* as a universal lifecycle marker rather than domain state. The interesting
|
|
10
|
+
* state is entirely in the context, which is reactive via `snapshot`.
|
|
11
|
+
*
|
|
12
|
+
* Use this when the actor has context that needs to be reactive but no
|
|
13
|
+
* meaningful state machine (e.g., a message-driven model with DOM side
|
|
14
|
+
* effects). For actors that need per-state behavior, use `createMachineActor`.
|
|
15
|
+
*/
|
|
16
|
+
interface TransitionActor<Context extends object, Message extends {
|
|
17
|
+
type: string;
|
|
18
|
+
}> extends Machine<ActorSnapshot<'active' | 'destroyed', Context>> {
|
|
19
|
+
send(message: Message): void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates a reducer-shaped actor from an initial context and a reducer function.
|
|
23
|
+
*
|
|
24
|
+
* The reducer receives the current context and a message and returns the next
|
|
25
|
+
* context. Returning the same reference (by identity) skips the signal update —
|
|
26
|
+
* so early-returning `context` unchanged is both the no-op and the optimization.
|
|
27
|
+
*
|
|
28
|
+
* Side effects (e.g. DOM mutations) may be performed inside the reducer.
|
|
29
|
+
* They run synchronously before the signal is updated.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const actor = createTransitionActor(
|
|
33
|
+
* { count: 0 },
|
|
34
|
+
* (context, message: { type: 'increment' }) => ({ count: context.count + 1 })
|
|
35
|
+
* );
|
|
36
|
+
*/
|
|
37
|
+
declare function createTransitionActor<Context extends object, Message extends {
|
|
38
|
+
type: string;
|
|
39
|
+
}>(initialContext: Context, reducer: (context: Context, message: Message) => Context): TransitionActor<Context, Message>;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { TransitionActor, createTransitionActor };
|
|
42
|
+
//# sourceMappingURL=create-transition-actor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-transition-actor.d.ts","names":[],"sources":["../../../../src/core/actors/create-transition-actor.ts"],"mappings":";;;;;;AAoBA;;;;;;;;;UAAiB,eAAA;EAA0D,IAAA;AAAA,WACjE,OAAA,CAAQ,aAAA,yBAAsC,OAAA;EACtD,IAAA,CAAK,OAAA,EAAS,OAAA;AAAA;;;;;;;AAuBhB;;;;;;;;;;iBAAgB,qBAAA;EAAgE,IAAA;AAAA,EAAA,CAC9E,cAAA,EAAgB,OAAA,EAChB,OAAA,GAAU,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAA,KAAY,OAAA,GAChD,eAAA,CAAgB,OAAA,EAAS,OAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { untrack, update } from "
|
|
2
|
-
import { createMachineCore } from "
|
|
3
|
-
//#region src/core/create-transition-actor.ts
|
|
1
|
+
import { untrack, update } from "../signals/primitives.js";
|
|
2
|
+
import { createMachineCore } from "../machine.js";
|
|
3
|
+
//#region src/core/actors/create-transition-actor.ts
|
|
4
4
|
/**
|
|
5
5
|
* Creates a reducer-shaped actor from an initial context and a reducer function.
|
|
6
6
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-transition-actor.js","names":[],"sources":["../../../../src/core/actors/create-transition-actor.ts"],"sourcesContent":["import type { Machine } from '../machine';\nimport { createMachineCore } from '../machine';\nimport { untrack, update } from '../signals/primitives';\nimport type { ActorSnapshot } from './actor';\n\n// =============================================================================\n// Definition types\n// =============================================================================\n\n/**\n * A reducer-shaped actor: `(context, message) => context`.\n *\n * No finite states — the snapshot carries `value: 'active' | 'destroyed'`\n * as a universal lifecycle marker rather than domain state. The interesting\n * state is entirely in the context, which is reactive via `snapshot`.\n *\n * Use this when the actor has context that needs to be reactive but no\n * meaningful state machine (e.g., a message-driven model with DOM side\n * effects). For actors that need per-state behavior, use `createMachineActor`.\n */\nexport interface TransitionActor<Context extends object, Message extends { type: string }>\n extends Machine<ActorSnapshot<'active' | 'destroyed', Context>> {\n send(message: Message): void;\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\n/**\n * Creates a reducer-shaped actor from an initial context and a reducer function.\n *\n * The reducer receives the current context and a message and returns the next\n * context. Returning the same reference (by identity) skips the signal update —\n * so early-returning `context` unchanged is both the no-op and the optimization.\n *\n * Side effects (e.g. DOM mutations) may be performed inside the reducer.\n * They run synchronously before the signal is updated.\n *\n * @example\n * const actor = createTransitionActor(\n * { count: 0 },\n * (context, message: { type: 'increment' }) => ({ count: context.count + 1 })\n * );\n */\nexport function createTransitionActor<Context extends object, Message extends { type: string }>(\n initialContext: Context,\n reducer: (context: Context, message: Message) => Context\n): TransitionActor<Context, Message> {\n const { snapshotSignal, getState, transition } = createMachineCore<\n 'active' | 'destroyed',\n ActorSnapshot<'active' | 'destroyed', Context>\n >({ value: 'active', context: initialContext });\n\n const getContext = (): Context => untrack(() => snapshotSignal.get().context);\n const setContext = (context: Context): void => update(snapshotSignal, { context });\n\n return {\n get snapshot() {\n return snapshotSignal;\n },\n\n send(message: Message): void {\n if (getState() === 'destroyed') return;\n const context = getContext();\n const newContext = reducer(context, message);\n if (newContext !== context) setContext(newContext);\n },\n\n destroy(): void {\n if (getState() === 'destroyed') return;\n transition('destroyed');\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,sBACd,gBACA,SACmC;CACnC,MAAM,EAAE,gBAAgB,UAAU,eAAe,kBAG/C;EAAE,OAAO;EAAU,SAAS;EAAgB,CAAC;CAE/C,MAAM,mBAA4B,cAAc,eAAe,KAAK,CAAC,QAAQ;CAC7E,MAAM,cAAc,YAA2B,OAAO,gBAAgB,EAAE,SAAS,CAAC;AAElF,QAAO;EACL,IAAI,WAAW;AACb,UAAO;;EAGT,KAAK,SAAwB;AAC3B,OAAI,UAAU,KAAK,YAAa;GAChC,MAAM,UAAU,YAAY;GAC5B,MAAM,aAAa,QAAQ,SAAS,QAAQ;AAC5C,OAAI,eAAe,QAAS,YAAW,WAAW;;EAGpD,UAAgB;AACd,OAAI,UAAU,KAAK,YAAa;AAChC,cAAW,YAAY;;EAE1B"}
|