@bubo-squared/gyroview 0.1.0
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/CHANGELOG.md +32 -0
- package/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/define.d.ts +3 -0
- package/dist/define.js +4 -0
- package/dist/index.d.ts +959 -0
- package/dist/index.js +13 -0
- package/dist/packages/adapters/blob/src/BlobRandomAccessSource.js +37 -0
- package/dist/packages/adapters/blob/src/index.js +2 -0
- package/dist/packages/adapters/fetch/src/HttpRangeSource.js +194 -0
- package/dist/packages/adapters/fetch/src/HttpResourceLocator.js +35 -0
- package/dist/packages/adapters/fetch/src/httpRequest.js +126 -0
- package/dist/packages/adapters/fetch/src/index.js +3 -0
- package/dist/packages/adapters/mediabunny/src/MediabunnyAudioSegments.js +133 -0
- package/dist/packages/adapters/mediabunny/src/MediabunnyDemuxer.js +63 -0
- package/dist/packages/adapters/mediabunny/src/MediabunnyVideoTrackReader.js +84 -0
- package/dist/packages/adapters/mediabunny/src/SegmentChannel.js +84 -0
- package/dist/packages/adapters/mediabunny/src/bufferSources.js +12 -0
- package/dist/packages/adapters/mediabunny/src/index.js +2 -0
- package/dist/packages/adapters/mse-audio/src/MediaSourceAudioClock.js +139 -0
- package/dist/packages/adapters/mse-audio/src/SourceBufferFeeder.js +174 -0
- package/dist/packages/adapters/mse-audio/src/events.js +26 -0
- package/dist/packages/adapters/mse-audio/src/index.js +2 -0
- package/dist/packages/adapters/mse-audio/src/mediaSourceSupport.js +82 -0
- package/dist/packages/adapters/three/src/ThreeFrameRenderer.js +274 -0
- package/dist/packages/adapters/three/src/compileAndProve.js +14 -0
- package/dist/packages/adapters/three/src/fullscreenPass.js +52 -0
- package/dist/packages/adapters/three/src/index.js +2 -0
- package/dist/packages/adapters/three/src/lensTextures.js +25 -0
- package/dist/packages/adapters/three/src/pictureMaterials.js +44 -0
- package/dist/packages/adapters/three/src/renderInto.js +15 -0
- package/dist/packages/adapters/three/src/rendererUniforms.js +157 -0
- package/dist/packages/adapters/three/src/samplingStrategies.js +26 -0
- package/dist/packages/adapters/three/src/seamMeter/SeamMeterPass.js +79 -0
- package/dist/packages/adapters/three/src/seamMeter/rowMeans.js +38 -0
- package/dist/packages/adapters/three/src/shaderPrograms.js +66 -0
- package/dist/packages/adapters/three/src/shaders/analysis.frag.js +4 -0
- package/dist/packages/adapters/three/src/shaders/equirectangularRays.js +4 -0
- package/dist/packages/adapters/three/src/shaders/fixedJoin.js +4 -0
- package/dist/packages/adapters/three/src/shaders/fullscreen.vert.js +4 -0
- package/dist/packages/adapters/three/src/shaders/header.js +4 -0
- package/dist/packages/adapters/three/src/shaders/lensModels.js +4 -0
- package/dist/packages/adapters/three/src/shaders/lensSampling.js +4 -0
- package/dist/packages/adapters/three/src/shaders/lensTextures.js +4 -0
- package/dist/packages/adapters/three/src/shaders/rawLenses.frag.js +4 -0
- package/dist/packages/adapters/three/src/shaders/rectilinearRays.js +4 -0
- package/dist/packages/adapters/three/src/shaders/screenAreas.js +4 -0
- package/dist/packages/adapters/three/src/shaders/stitch.frag.js +4 -0
- package/dist/packages/adapters/three/src/webglRenderer.js +37 -0
- package/dist/packages/adapters/webcodecs/src/WebCodecsVideoDecoderPort.js +135 -0
- package/dist/packages/adapters/webcodecs/src/index.js +2 -0
- package/dist/packages/core/src/application/gainMatching/GainMatching.js +66 -0
- package/dist/packages/core/src/application/gainMatching/GainMatchingFrameSink.js +62 -0
- package/dist/packages/core/src/application/playback/ClockWatch.js +76 -0
- package/dist/packages/core/src/application/playback/DecodePipeline.js +188 -0
- package/dist/packages/core/src/application/playback/DecodeRun.js +93 -0
- package/dist/packages/core/src/application/playback/FramePairQueue.js +93 -0
- package/dist/packages/core/src/application/playback/FramePairer.js +60 -0
- package/dist/packages/core/src/application/playback/PlaybackSession.js +417 -0
- package/dist/packages/core/src/application/playback/SeekOrder.js +36 -0
- package/dist/packages/core/src/application/playback/SessionLifecycle.js +42 -0
- package/dist/packages/core/src/application/playback/StartGate.js +55 -0
- package/dist/packages/core/src/application/playback/TimeUpdates.js +31 -0
- package/dist/packages/core/src/application/playback/WallClock.js +46 -0
- package/dist/packages/core/src/application/playback/keyframeTimeAt.js +15 -0
- package/dist/packages/core/src/application/playback/probeDecoding.js +168 -0
- package/dist/packages/core/src/application/recording/frameTimesOf.js +22 -0
- package/dist/packages/core/src/application/recording/inspectLayout.js +21 -0
- package/dist/packages/core/src/application/recording/inspectRecording.js +124 -0
- package/dist/packages/core/src/application/recording/locateOtherLensFile.js +18 -0
- package/dist/packages/core/src/application/recording/motionOf.js +39 -0
- package/dist/packages/core/src/application/recording/readRecording.js +31 -0
- package/dist/packages/core/src/application/recording/timeRecording.js +57 -0
- package/dist/packages/core/src/application/stabilization/StabilizingFrameSink.js +31 -0
- package/dist/packages/core/src/domain/format/boxes/BoxLayout.js +7 -0
- package/dist/packages/core/src/domain/format/boxes/boxConstants.js +16 -0
- package/dist/packages/core/src/domain/format/boxes/scanBoxes.js +59 -0
- package/dist/packages/core/src/domain/format/calibration/CalibrationVersion.js +13 -0
- package/dist/packages/core/src/domain/format/calibration/layouts/CalibrationStringLayout.js +34 -0
- package/dist/packages/core/src/domain/format/calibration/layouts/LegacyCalibrationLayout.js +44 -0
- package/dist/packages/core/src/domain/format/calibration/layouts/MeiCalibrationLayout.js +45 -0
- package/dist/packages/core/src/domain/format/calibration/layouts/PolynomialCalibrationLayout.js +44 -0
- package/dist/packages/core/src/domain/format/calibration/offsetTokens.js +65 -0
- package/dist/packages/core/src/domain/format/calibration/parseOffsetString.js +52 -0
- package/dist/packages/core/src/domain/format/calibration/selectCalibration.js +46 -0
- package/dist/packages/core/src/domain/format/captureOrigin.js +20 -0
- package/dist/packages/core/src/domain/format/constants.js +33 -0
- package/dist/packages/core/src/domain/format/info/infoFields.js +110 -0
- package/dist/packages/core/src/domain/format/info/parseInfoRecord.js +90 -0
- package/dist/packages/core/src/domain/format/info/readInfoRecord.js +14 -0
- package/dist/packages/core/src/domain/format/layout/detectLensLayout.js +122 -0
- package/dist/packages/core/src/domain/format/naming/RecordingFileName.js +67 -0
- package/dist/packages/core/src/domain/format/records/TrailerRecords.js +83 -0
- package/dist/packages/core/src/domain/format/records/exposure/parseExposureRecord.js +48 -0
- package/dist/packages/core/src/domain/format/records/gyro/FloatGyroSampleLayout.js +39 -0
- package/dist/packages/core/src/domain/format/records/gyro/RawGyroSampleLayout.js +55 -0
- package/dist/packages/core/src/domain/format/records/gyro/SampleColumns.js +82 -0
- package/dist/packages/core/src/domain/format/records/gyro/gyroLayouts.js +12 -0
- package/dist/packages/core/src/domain/format/records/gyro/parseGyroRecord.js +129 -0
- package/dist/packages/core/src/domain/format/trailer/RecordHeader.js +23 -0
- package/dist/packages/core/src/domain/format/trailer/Trailer.js +23 -0
- package/dist/packages/core/src/domain/format/trailer/TrailerFooter.js +27 -0
- package/dist/packages/core/src/domain/format/trailer/locateRecords.js +80 -0
- package/dist/packages/core/src/domain/format/trailer/parseRecordIndex.js +28 -0
- package/dist/packages/core/src/domain/format/trailer/readTrailer.js +32 -0
- package/dist/packages/core/src/domain/motion/exposure/ExposureRecord.js +53 -0
- package/dist/packages/core/src/domain/motion/gyro/GyroTrack.js +60 -0
- package/dist/packages/core/src/domain/motion/gyro/medianStep.js +11 -0
- package/dist/packages/core/src/domain/motion/gyro/repairedTimeline.js +101 -0
- package/dist/packages/core/src/domain/motion/imu/ImuFrame.js +112 -0
- package/dist/packages/core/src/domain/motion/orientation/OrientationTrack.js +146 -0
- package/dist/packages/core/src/domain/motion/orientation/estimateGyroBias.js +64 -0
- package/dist/packages/core/src/domain/motion/orientation/gravity.js +97 -0
- package/dist/packages/core/src/domain/motion/stabilization/Stabilizer.js +13 -0
- package/dist/packages/core/src/domain/motion/stabilization/stabilizers.js +86 -0
- package/dist/packages/core/src/domain/motion/timing/CaptureClock.js +41 -0
- package/dist/packages/core/src/domain/motion/timing/FrameTimes.js +92 -0
- package/dist/packages/core/src/domain/motion/timing/frameTimeSources.js +61 -0
- package/dist/packages/core/src/domain/motion/timing/resolveFrameTimes.js +68 -0
- package/dist/packages/core/src/domain/optics/EquidistantModel.js +39 -0
- package/dist/packages/core/src/domain/optics/MeiModel.js +45 -0
- package/dist/packages/core/src/domain/optics/PolynomialModel.js +44 -0
- package/dist/packages/core/src/domain/optics/gainMatch.js +62 -0
- package/dist/packages/core/src/domain/optics/lensGeometry.js +18 -0
- package/dist/packages/core/src/domain/optics/lensPose.js +35 -0
- package/dist/packages/core/src/domain/optics/opticsConstants.js +5 -0
- package/dist/packages/core/src/domain/playback/PlayerState.js +83 -0
- package/dist/packages/core/src/domain/stitching/LensLayout.js +21 -0
- package/dist/packages/core/src/domain/stitching/StitchingSetup.js +78 -0
- package/dist/packages/core/src/domain/stitching/seamDisparity.js +4 -0
- package/dist/packages/core/src/domain/stitching/seamDisparityField.js +5 -0
- package/dist/packages/core/src/domain/stitching/seamJoin.js +16 -0
- package/dist/packages/core/src/domain/stitching/seamMismatch.js +1 -0
- package/dist/packages/core/src/domain/stitching/seamRing.js +4 -0
- package/dist/packages/core/src/domain/stitching/seamStrip.js +26 -0
- package/dist/packages/core/src/domain/view/Framing.js +31 -0
- package/dist/packages/core/src/domain/view/PictureQuality.js +26 -0
- package/dist/packages/core/src/domain/view/ViewMode.js +9 -0
- package/dist/packages/core/src/domain/view/ViewState.js +48 -0
- package/dist/packages/core/src/domain/view/lensTilesView.js +63 -0
- package/dist/packages/core/src/domain/view/magnification.js +103 -0
- package/dist/packages/core/src/domain/view/normalView.js +29 -0
- package/dist/packages/core/src/domain/view/panoramaView.js +99 -0
- package/dist/packages/core/src/domain/view/rectilinear.js +40 -0
- package/dist/packages/core/src/domain/view/screenLayout.js +113 -0
- package/dist/packages/core/src/domain/view/viewGestures.js +98 -0
- package/dist/packages/core/src/domain/view/viewModes.js +14 -0
- package/dist/packages/core/src/index.js +59 -0
- package/dist/packages/core/src/ports/FramePair.js +6 -0
- package/dist/packages/core/src/shared/async/Deferred.js +42 -0
- package/dist/packages/core/src/shared/async/RunStop.js +40 -0
- package/dist/packages/core/src/shared/binary/ByteRange.js +38 -0
- package/dist/packages/core/src/shared/binary/ByteReader.js +77 -0
- package/dist/packages/core/src/shared/errors/GyroViewError.js +81 -0
- package/dist/packages/core/src/shared/errors/reportLater.js +11 -0
- package/dist/packages/core/src/shared/events/Outbox.js +68 -0
- package/dist/packages/core/src/shared/events/TypedEmitter.js +55 -0
- package/dist/packages/core/src/shared/keysOf.js +10 -0
- package/dist/packages/core/src/shared/lazy.js +11 -0
- package/dist/packages/core/src/shared/math/Matrix3.js +93 -0
- package/dist/packages/core/src/shared/math/Quaternion.js +133 -0
- package/dist/packages/core/src/shared/math/Vector3.js +54 -0
- package/dist/packages/core/src/shared/math/clamp.js +9 -0
- package/dist/packages/core/src/shared/protobuf/ProtobufMessage.js +157 -0
- package/dist/packages/core/src/shared/text/urlPath.js +31 -0
- package/dist/packages/core/src/shared/text/utf8.js +12 -0
- package/dist/packages/core/src/shared/units/angle.js +22 -0
- package/dist/packages/core/src/shared/units/time.js +13 -0
- package/dist/packages/player/src/PlayerSource.js +15 -0
- package/dist/packages/player/src/browserPlayer.js +18 -0
- package/dist/packages/player/src/choices.js +25 -0
- package/dist/packages/player/src/composition/Disposables.js +31 -0
- package/dist/packages/player/src/composition/browserPorts.js +46 -0
- package/dist/packages/player/src/composition/buildPipeline.js +153 -0
- package/dist/packages/player/src/composition/ensureDecodable.js +63 -0
- package/dist/packages/player/src/composition/openInputs.js +179 -0
- package/dist/packages/player/src/composition/openRecording.js +42 -0
- package/dist/packages/player/src/controls/ChoiceMenu.js +113 -0
- package/dist/packages/player/src/controls/PictureMenus.js +47 -0
- package/dist/packages/player/src/controls/SeekBar.js +125 -0
- package/dist/packages/player/src/controls/SoundControls.js +41 -0
- package/dist/packages/player/src/controls/TransportButtons.js +31 -0
- package/dist/packages/player/src/controls/ViewGestures.js +136 -0
- package/dist/packages/player/src/controls/Wording.js +78 -0
- package/dist/packages/player/src/controls/controlParts.js +36 -0
- package/dist/packages/player/src/controls/controls.js +4 -0
- package/dist/packages/player/src/controls/controlsBar.js +23 -0
- package/dist/packages/player/src/controls/controlsMarkup.js +85 -0
- package/dist/packages/player/src/controls/customControls.js +59 -0
- package/dist/packages/player/src/controls/formatTime.js +19 -0
- package/dist/packages/player/src/controls/icons.js +40 -0
- package/dist/packages/player/src/controls/keyboard.js +118 -0
- package/dist/packages/player/src/controls/messages.js +94 -0
- package/dist/packages/player/src/controls/parseMarkup.js +31 -0
- package/dist/packages/player/src/controls/viewButtons.js +14 -0
- package/dist/packages/player/src/element/ElementLoads.js +119 -0
- package/dist/packages/player/src/element/FullscreenToggle.js +39 -0
- package/dist/packages/player/src/element/GyroViewElement.js +313 -0
- package/dist/packages/player/src/element/IdleWatcher.js +71 -0
- package/dist/packages/player/src/element/TypedEventElement.js +22 -0
- package/dist/packages/player/src/element/accessibleRegion.js +19 -0
- package/dist/packages/player/src/element/attributeNames.js +51 -0
- package/dist/packages/player/src/element/attributes.js +101 -0
- package/dist/packages/player/src/element/defineGyroView.js +21 -0
- package/dist/packages/player/src/element/earlyProperties.js +36 -0
- package/dist/packages/player/src/element/elementSource.js +23 -0
- package/dist/packages/player/src/element/liveSettings.js +138 -0
- package/dist/packages/player/src/element/playbackAttributes.js +53 -0
- package/dist/packages/player/src/element/playerEventMirror.js +33 -0
- package/dist/packages/player/src/element/reflectedProperties.js +78 -0
- package/dist/packages/player/src/element/styles.js +4 -0
- package/dist/packages/player/src/element/template.js +47 -0
- package/dist/packages/player/src/index.js +10 -0
- package/dist/packages/player/src/inspectRecording.js +22 -0
- package/dist/packages/player/src/player/DrawingBufferFit.js +77 -0
- package/dist/packages/player/src/player/FrameLoop.js +40 -0
- package/dist/packages/player/src/player/PictureSettings.js +60 -0
- package/dist/packages/player/src/player/Player.js +377 -0
- package/dist/packages/player/src/player/PlayerEvents.js +28 -0
- package/dist/packages/player/src/player/PlayerPhase.js +21 -0
- package/dist/packages/player/src/player/PlayerSound.js +61 -0
- package/dist/packages/player/src/player/PlayerView.js +113 -0
- package/dist/packages/player/src/player/SessionRelay.js +66 -0
- package/dist/packages/player/src/player/ensureFinite.js +26 -0
- package/dist/packages/player/src/player/loadRecording.js +65 -0
- package/dist/packages/player/src/player/transportEvents.js +29 -0
- package/dist/standalone.js +4919 -0
- package/package.json +73 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { degrees } from "../../../core/src/shared/units/angle.js";
|
|
2
|
+
import { GyroViewError } from "../../../core/src/shared/errors/GyroViewError.js";
|
|
3
|
+
import { keysOf } from "../../../core/src/shared/keysOf.js";
|
|
4
|
+
import "../../../core/src/index.js";
|
|
5
|
+
import { pictureQualityOf, stabilizationModeOf, viewModeOf } from "../choices.js";
|
|
6
|
+
import { ensureFinite } from "../player/ensureFinite.js";
|
|
7
|
+
//#region ../../packages/player/src/element/liveSettings.ts
|
|
8
|
+
/**
|
|
9
|
+
* Every name of {@link LiveSettings} once, for what must know the settings before the element
|
|
10
|
+
* defines them.
|
|
11
|
+
*/
|
|
12
|
+
var LIVE_SETTING_NAMES = keysOf({
|
|
13
|
+
stabilization: true,
|
|
14
|
+
viewMode: true,
|
|
15
|
+
quality: true,
|
|
16
|
+
fov: true,
|
|
17
|
+
yaw: true,
|
|
18
|
+
pitch: true,
|
|
19
|
+
muted: true,
|
|
20
|
+
loop: true,
|
|
21
|
+
volume: true
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Properties that read and change the player's settings as they are now, the way
|
|
25
|
+
* `HTMLMediaElement.muted` does: the attribute of the same name configures the setting, the
|
|
26
|
+
* property reports what is in effect however it was last changed (attribute, menu, keyboard,
|
|
27
|
+
* gesture or script). An unset choice, angle or volume is left as it is, any other value it
|
|
28
|
+
* cannot take is refused; `muted` and `loop` take any value as a boolean.
|
|
29
|
+
*/
|
|
30
|
+
function defineLiveSettings(element, player) {
|
|
31
|
+
const accessors = {
|
|
32
|
+
stabilization: {
|
|
33
|
+
get: () => player.stabilization,
|
|
34
|
+
set: unlessUnset((value) => {
|
|
35
|
+
player.setStabilization(stabilizationModeFrom(value));
|
|
36
|
+
})
|
|
37
|
+
},
|
|
38
|
+
viewMode: {
|
|
39
|
+
get: () => player.viewMode,
|
|
40
|
+
set: unlessUnset((value) => {
|
|
41
|
+
player.setViewMode(viewModeFrom(value));
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
quality: {
|
|
45
|
+
get: () => player.quality,
|
|
46
|
+
set: unlessUnset((value) => {
|
|
47
|
+
player.setQuality(pictureQualityFrom(value));
|
|
48
|
+
})
|
|
49
|
+
},
|
|
50
|
+
...viewAccessors(player),
|
|
51
|
+
...soundAccessors(player)
|
|
52
|
+
};
|
|
53
|
+
for (const [name, accessor] of Object.entries(accessors)) Object.defineProperty(element, name, {
|
|
54
|
+
configurable: true,
|
|
55
|
+
enumerable: true,
|
|
56
|
+
...accessor
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function viewAccessors(player) {
|
|
60
|
+
const angle = (key, property) => ({
|
|
61
|
+
get: () => player.view[key],
|
|
62
|
+
set: unlessUnset((value) => {
|
|
63
|
+
player.setView({
|
|
64
|
+
...player.view,
|
|
65
|
+
[key]: angleOf(value, property)
|
|
66
|
+
});
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
fov: angle("fieldOfView", "fov"),
|
|
71
|
+
yaw: angle("yaw", "yaw"),
|
|
72
|
+
pitch: angle("pitch", "pitch")
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function soundAccessors(player) {
|
|
76
|
+
return {
|
|
77
|
+
muted: {
|
|
78
|
+
get: () => player.isMuted,
|
|
79
|
+
set: (value) => {
|
|
80
|
+
player.setMuted(Boolean(value));
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
loop: {
|
|
84
|
+
get: () => player.isLooping,
|
|
85
|
+
set: (value) => {
|
|
86
|
+
player.setLooping(Boolean(value));
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
volume: {
|
|
90
|
+
get: () => player.volume,
|
|
91
|
+
set: unlessUnset((value) => {
|
|
92
|
+
player.setVolume(numberOf(value, "volume"));
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The stabilization mode `value` names; anything else is refused, as the element's methods and
|
|
99
|
+
* the embed commands refuse it.
|
|
100
|
+
*/
|
|
101
|
+
function stabilizationModeFrom(value) {
|
|
102
|
+
return accepted(value, stabilizationModeOf, "stabilization");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The view mode `value` names; anything else is refused.
|
|
106
|
+
*/
|
|
107
|
+
function viewModeFrom(value) {
|
|
108
|
+
return accepted(value, viewModeOf, "viewMode");
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The picture quality `value` names; anything else is refused.
|
|
112
|
+
*/
|
|
113
|
+
function pictureQualityFrom(value) {
|
|
114
|
+
return accepted(value, pictureQualityOf, "quality");
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A setting unset leaves it as it is, as removing its attribute does: a framework unsets a
|
|
118
|
+
* property it no longer passes with `undefined` (React), `null` or an empty string (Preact).
|
|
119
|
+
*/
|
|
120
|
+
function unlessUnset(set) {
|
|
121
|
+
return (value) => {
|
|
122
|
+
if (value !== void 0 && value !== null && value !== "") set(value);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function accepted(value, parse, property) {
|
|
126
|
+
const choice = typeof value === "string" ? parse(value) : void 0;
|
|
127
|
+
if (choice === void 0) throw new GyroViewError("invalid-argument", `${property} cannot be ${String(value)}`);
|
|
128
|
+
return choice;
|
|
129
|
+
}
|
|
130
|
+
function angleOf(value, property) {
|
|
131
|
+
return degrees(numberOf(value, property));
|
|
132
|
+
}
|
|
133
|
+
function numberOf(value, property) {
|
|
134
|
+
ensureFinite(value, property);
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
export { LIVE_SETTING_NAMES, defineLiveSettings, pictureQualityFrom, stabilizationModeFrom, viewModeFrom };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { STABILIZATION_MODES } from "../../../core/src/domain/motion/stabilization/Stabilizer.js";
|
|
2
|
+
import { PICTURE_QUALITIES } from "../../../core/src/domain/view/PictureQuality.js";
|
|
3
|
+
import { VIEW_MODES } from "../../../core/src/domain/view/ViewMode.js";
|
|
4
|
+
import "../../../core/src/index.js";
|
|
5
|
+
import { choiceOf } from "../choices.js";
|
|
6
|
+
import { PlaybackAttribute } from "./attributeNames.js";
|
|
7
|
+
import { ignoredChoiceWarning, isBooleanAttributeSet, shouldMatchGains } from "./attributes.js";
|
|
8
|
+
//#region ../../packages/player/src/element/playbackAttributes.ts
|
|
9
|
+
/**
|
|
10
|
+
* An attribute naming one of `choices`: applied when known, warned about otherwise. Removing the
|
|
11
|
+
* attribute leaves the setting as it is.
|
|
12
|
+
*/
|
|
13
|
+
function choiceApplier(attribute, choices, apply) {
|
|
14
|
+
return ({ player, warn }, value) => {
|
|
15
|
+
const choice = choiceOf(value, choices);
|
|
16
|
+
if (choice) apply(player, choice);
|
|
17
|
+
else if (value !== null) warn(ignoredChoiceWarning(attribute, value, choices));
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* What each attribute that changes playback without reloading does.
|
|
22
|
+
*/
|
|
23
|
+
var APPLIERS = {
|
|
24
|
+
[PlaybackAttribute.Stabilization]: choiceApplier(PlaybackAttribute.Stabilization, STABILIZATION_MODES, (player, mode) => {
|
|
25
|
+
player.setStabilization(mode);
|
|
26
|
+
}),
|
|
27
|
+
[PlaybackAttribute.ViewMode]: choiceApplier(PlaybackAttribute.ViewMode, VIEW_MODES, (player, mode) => {
|
|
28
|
+
player.setViewMode(mode);
|
|
29
|
+
}),
|
|
30
|
+
[PlaybackAttribute.Quality]: choiceApplier(PlaybackAttribute.Quality, PICTURE_QUALITIES, (player, quality) => {
|
|
31
|
+
player.setQuality(quality);
|
|
32
|
+
}),
|
|
33
|
+
[PlaybackAttribute.Muted]: ({ player }, value) => {
|
|
34
|
+
player.setMuted(isBooleanAttributeSet(value));
|
|
35
|
+
},
|
|
36
|
+
[PlaybackAttribute.Loop]: ({ player }, value) => {
|
|
37
|
+
player.setLooping(isBooleanAttributeSet(value));
|
|
38
|
+
},
|
|
39
|
+
[PlaybackAttribute.Poster]: ({ posterImage }, value) => {
|
|
40
|
+
posterImage.src = value ?? "";
|
|
41
|
+
},
|
|
42
|
+
[PlaybackAttribute.GainMatch]: ({ player }, value) => {
|
|
43
|
+
player.setGainMatching(shouldMatchGains(value));
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
function isApplied(name) {
|
|
47
|
+
return Object.hasOwn(APPLIERS, name);
|
|
48
|
+
}
|
|
49
|
+
function applyPlaybackAttribute(targets, name, value) {
|
|
50
|
+
if (isApplied(name)) APPLIERS[name](targets, value);
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { applyPlaybackAttribute };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { queryShadow } from "../controls/controlParts.js";
|
|
2
|
+
import { PLAYER_EVENT_NAMES } from "../player/PlayerEvents.js";
|
|
3
|
+
//#region ../../packages/player/src/element/playerEventMirror.ts
|
|
4
|
+
/**
|
|
5
|
+
* The element's own bookkeeping runs before the events reach page listeners, so a listener sees
|
|
6
|
+
* the attributes already matching the event it hears: the status and frame attributes, the idle
|
|
7
|
+
* state and the error overlay. Every player event is then dispatched as a composed `CustomEvent`
|
|
8
|
+
* of the same name, the payload in `detail`.
|
|
9
|
+
*/
|
|
10
|
+
function mirrorPlayerEvents(player, target) {
|
|
11
|
+
const { element, shadow, idle, wording } = target;
|
|
12
|
+
const errorMessage = queryShadow(shadow, ".error-message", HTMLElement);
|
|
13
|
+
const errorCode = queryShadow(shadow, ".error-code", HTMLElement);
|
|
14
|
+
player.events.on("statuschange", (status) => {
|
|
15
|
+
element.dataset["status"] = status;
|
|
16
|
+
idle.refresh();
|
|
17
|
+
});
|
|
18
|
+
player.events.on("frame", () => {
|
|
19
|
+
element.dataset["hasFrame"] = "";
|
|
20
|
+
});
|
|
21
|
+
player.events.on("error", (error) => {
|
|
22
|
+
wording.showError(errorMessage, error.code);
|
|
23
|
+
errorCode.textContent = error.code;
|
|
24
|
+
});
|
|
25
|
+
for (const name of PLAYER_EVENT_NAMES) player.events.on(name, (detail) => {
|
|
26
|
+
element.dispatchEvent(new CustomEvent(name, {
|
|
27
|
+
detail,
|
|
28
|
+
composed: true
|
|
29
|
+
}));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { mirrorPlayerEvents };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//#region ../../packages/player/src/element/reflectedProperties.ts
|
|
2
|
+
/**
|
|
3
|
+
* Defines properties on a custom element that read and write attributes of the same name, the
|
|
4
|
+
* way `img.src` mirrors its attribute, so the class body stays free of near-identical accessors.
|
|
5
|
+
*/
|
|
6
|
+
function defineStringProperties(element, names) {
|
|
7
|
+
for (const name of names) Object.defineProperty(element, propertyNameOf(name), {
|
|
8
|
+
configurable: true,
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get() {
|
|
11
|
+
return this.getAttribute(name);
|
|
12
|
+
},
|
|
13
|
+
set(value) {
|
|
14
|
+
writeAttribute(this, name, value);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Boolean attributes, the value coerced as a media element's `autoplay` coerces it:
|
|
20
|
+
* `toggleAttribute` would take `undefined` for no force at all and flip the attribute.
|
|
21
|
+
*/
|
|
22
|
+
function defineBooleanProperties(element, names) {
|
|
23
|
+
for (const name of names) Object.defineProperty(element, propertyNameOf(name), {
|
|
24
|
+
configurable: true,
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get() {
|
|
27
|
+
return this.hasAttribute(name);
|
|
28
|
+
},
|
|
29
|
+
set(isSet) {
|
|
30
|
+
this.toggleAttribute(name, Boolean(isSet));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Enumerated attributes, whose property reads the keyword in effect, however the attribute
|
|
36
|
+
* spells it, and writes the attribute.
|
|
37
|
+
*/
|
|
38
|
+
function defineKeywordProperties(element, attributes) {
|
|
39
|
+
for (const attribute of attributes) Object.defineProperty(element, propertyNameOf(attribute.name), {
|
|
40
|
+
configurable: true,
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get() {
|
|
43
|
+
return keywordOf(attribute, this.getAttribute(attribute.name));
|
|
44
|
+
},
|
|
45
|
+
set(value) {
|
|
46
|
+
writeAttribute(this, attribute.name, value);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The keyword an enumerated attribute's value names, ignoring case and spacing; the fallback for
|
|
52
|
+
* an absent or unknown one.
|
|
53
|
+
*/
|
|
54
|
+
function keywordOf(attribute, value) {
|
|
55
|
+
const spoken = value?.trim().toLowerCase();
|
|
56
|
+
return attribute.keywords.find((keyword) => keyword === spoken) ?? attribute.fallback;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* `null` or `undefined` removes the attribute, as assigning either to `img.alt` would not but
|
|
60
|
+
* `removeAttribute` does: a framework unsetting a property assigns `undefined`, which would
|
|
61
|
+
* otherwise be written as the text "undefined".
|
|
62
|
+
*/
|
|
63
|
+
function writeAttribute(element, name, value) {
|
|
64
|
+
if (value === null || value === void 0) {
|
|
65
|
+
element.removeAttribute(name);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
element.setAttribute(name, value);
|
|
69
|
+
}
|
|
70
|
+
var HYPHENATED_LETTER = /-(?<letter>[a-z])/gu;
|
|
71
|
+
/**
|
|
72
|
+
* `gain-match` is the property `gainMatch`, as the DOM does for `data-*` and `aria-*`.
|
|
73
|
+
*/
|
|
74
|
+
function propertyNameOf(attribute) {
|
|
75
|
+
return attribute.replaceAll(HYPHENATED_LETTER, (_match, letter) => letter.toUpperCase());
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { defineBooleanProperties, defineKeywordProperties, defineStringProperties, keywordOf, propertyNameOf, writeAttribute };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
//#region ../../packages/player/src/element/styles.css?raw
|
|
2
|
+
var styles_default = ":host {\n --gyro-view-accent: #4cc2ff;\n --gyro-view-controls-background: rgb(0 0 0 / 55%);\n --gyro-view-text: #f4f4f4;\n --gyro-view-font: system-ui, -apple-system, 'Segoe UI', sans-serif;\n --gyro-view-radius: 6px;\n\n display: block;\n position: relative;\n width: 100%;\n aspect-ratio: 16 / 9;\n background: #000;\n color: var(--gyro-view-text);\n font-family: var(--gyro-view-font);\n overflow: hidden;\n user-select: none;\n -webkit-user-select: none;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host(:focus-visible) {\n outline: 2px solid var(--gyro-view-accent);\n outline-offset: 2px;\n}\n\n/*\n * Pinned over the page where the Fullscreen API is refused (iPhone Safari). Like the browser's\n * own fullscreen rules it overrides the size, margins and place the page gave the element, and\n * the insets size it to the visible viewport, where 100vh would reach under Safari's toolbars.\n */\n:host([data-fill]) {\n position: fixed !important;\n inset: 0 !important;\n box-sizing: border-box !important;\n width: auto !important;\n height: auto !important;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n margin: 0 !important;\n transform: none !important;\n aspect-ratio: auto !important;\n z-index: 2147483000 !important;\n}\n\n:host(:fullscreen) {\n width: 100%;\n height: 100%;\n aspect-ratio: auto;\n}\n\n/* The size container the controls fit themselves to: the player's size, not the page's. Its\n size never depends on its content, which size containment requires. */\n.stage {\n position: absolute;\n inset: 0;\n container-type: size;\n}\n\ncanvas {\n display: block;\n width: 100%;\n height: 100%;\n touch-action: none;\n}\n\n.poster {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n pointer-events: none;\n}\n\n:host([data-has-frame]) .poster,\n:host(:not([poster])) .poster {\n display: none;\n}\n\n.overlay {\n position: absolute;\n inset: 0;\n display: none;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 0.5rem;\n padding: 1rem;\n text-align: center;\n background: rgb(0 0 0 / 45%);\n}\n\n:host([data-status='loading']) .overlay.loading,\n:host([data-status='buffering']) .overlay.loading,\n:host([data-status='error']) .overlay.error {\n display: flex;\n}\n\n:host([data-status='buffering']) .overlay.loading {\n background: transparent;\n pointer-events: none;\n}\n\n.spinner {\n width: 2.5rem;\n height: 2.5rem;\n border: 3px solid rgb(255 255 255 / 25%);\n border-top-color: var(--gyro-view-accent);\n border-radius: 50%;\n animation: gyro-view-spin 0.9s linear infinite;\n}\n\n@keyframes gyro-view-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* A viewer who asked for less motion still sees that it loads, three times slower. */\n@media (prefers-reduced-motion: reduce) {\n .spinner {\n animation-duration: 2.7s;\n }\n}\n\n.error-code {\n font-size: 0.8rem;\n opacity: 0.7;\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { styles_default as default };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { lazy } from "../../../core/src/shared/lazy.js";
|
|
2
|
+
import "../../../core/src/index.js";
|
|
3
|
+
import { parseMarkup } from "../controls/parseMarkup.js";
|
|
4
|
+
import { CONTROLS_STYLES, controlsMarkup } from "../controls/controlsMarkup.js";
|
|
5
|
+
import styles_default from "./styles.js";
|
|
6
|
+
//#region ../../packages/player/src/element/template.ts
|
|
7
|
+
/**
|
|
8
|
+
* The shadow tree: the stage with the canvas, poster, audio element and overlays, and the
|
|
9
|
+
* controls' own markup. Class names are the contract between this markup, the stylesheet and the
|
|
10
|
+
* code that queries it; `part` names are the embedder's styling hooks. The words are the
|
|
11
|
+
* wording's to fill in.
|
|
12
|
+
*/
|
|
13
|
+
function elementMarkup() {
|
|
14
|
+
return `
|
|
15
|
+
<div class="stage" part="stage">
|
|
16
|
+
<canvas part="canvas"></canvas>
|
|
17
|
+
<img class="poster" part="poster" alt="" />
|
|
18
|
+
<audio hidden></audio>
|
|
19
|
+
<div class="overlay loading" part="loading" role="status" data-label="loading">
|
|
20
|
+
<div class="spinner"></div>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="overlay error" part="error" role="alert">
|
|
23
|
+
<p class="error-message" part="error-message"></p>
|
|
24
|
+
<p class="error-code" part="error-code"></p>
|
|
25
|
+
</div>
|
|
26
|
+
${controlsMarkup()}
|
|
27
|
+
</div>
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
var parsedTree = lazy(() => parseMarkup(elementMarkup()));
|
|
31
|
+
var stylesheets = lazy(() => [styles_default, CONTROLS_STYLES].map((css) => stylesheetOf(css)));
|
|
32
|
+
/**
|
|
33
|
+
* Fills a new element's shadow root with a copy of the tree, parsed once per page, and adopts
|
|
34
|
+
* the stylesheets, built once and shared by every element. A Content Security Policy governs
|
|
35
|
+
* `<style>` elements but not adopted stylesheets, so a page needs no `'unsafe-inline'` styles.
|
|
36
|
+
*/
|
|
37
|
+
function renderShadowTree(shadow) {
|
|
38
|
+
shadow.adoptedStyleSheets = stylesheets();
|
|
39
|
+
shadow.append(parsedTree().cloneNode(true));
|
|
40
|
+
}
|
|
41
|
+
function stylesheetOf(css) {
|
|
42
|
+
const sheet = new CSSStyleSheet();
|
|
43
|
+
sheet.replaceSync(css);
|
|
44
|
+
return sheet;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { renderShadowTree };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "./choices.js";
|
|
2
|
+
import "./element/reflectedProperties.js";
|
|
3
|
+
import "./player/ensureFinite.js";
|
|
4
|
+
import { attachKeyboard, attachViewGestures } from "./controls/customControls.js";
|
|
5
|
+
import { Player } from "./player/Player.js";
|
|
6
|
+
import { createBrowserPlayer } from "./browserPlayer.js";
|
|
7
|
+
import { inspectRecording } from "./inspectRecording.js";
|
|
8
|
+
import { GyroViewElement } from "./element/GyroViewElement.js";
|
|
9
|
+
import { GYRO_VIEW_TAG, defineGyroView } from "./element/defineGyroView.js";
|
|
10
|
+
export { GYRO_VIEW_TAG, GyroViewElement, Player, attachKeyboard, attachViewGestures, createBrowserPlayer, defineGyroView, inspectRecording };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { inspectRecording as inspectRecording$1 } from "../../core/src/application/recording/inspectRecording.js";
|
|
2
|
+
import "../../core/src/index.js";
|
|
3
|
+
import { browserSources } from "./composition/browserPorts.js";
|
|
4
|
+
//#region ../../packages/player/src/inspectRecording.ts
|
|
5
|
+
/**
|
|
6
|
+
* Reads what a recording's file holds without playing it (see `RecordingInspection`): from a URL,
|
|
7
|
+
* in byte ranges as playback reads it, or from a `Blob`, such as a `File` from a picker. Rejects
|
|
8
|
+
* with the `GyroViewError` a load would meet, for example `cors` or `invalid-trailer`.
|
|
9
|
+
*/
|
|
10
|
+
function inspectRecording(recording, options = {}) {
|
|
11
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
12
|
+
const source = browserSources(options.http ?? {}).open(inputOf(recording), signal);
|
|
13
|
+
return inspectRecording$1(source);
|
|
14
|
+
}
|
|
15
|
+
function inputOf(recording) {
|
|
16
|
+
return typeof recording === "string" ? { url: recording } : {
|
|
17
|
+
blob: recording,
|
|
18
|
+
name: recording instanceof File ? recording.name : ""
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { inspectRecording };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { clamp } from "../../../core/src/shared/math/clamp.js";
|
|
2
|
+
import { DEFAULT_PICTURE_QUALITY, pixelRatioCapOf } from "../../../core/src/domain/view/PictureQuality.js";
|
|
3
|
+
import "../../../core/src/index.js";
|
|
4
|
+
//#region ../../packages/player/src/player/DrawingBufferFit.ts
|
|
5
|
+
/**
|
|
6
|
+
* The drawing buffer size, in device pixels, for an element of the given CSS size on a screen
|
|
7
|
+
* of the given pixel ratio, drawn at the given quality.
|
|
8
|
+
*/
|
|
9
|
+
function drawingBufferSizeFor(cssSize, devicePixelRatio, quality = DEFAULT_PICTURE_QUALITY) {
|
|
10
|
+
const ratio = clamp(devicePixelRatio, 1, pixelRatioCapOf(quality));
|
|
11
|
+
return {
|
|
12
|
+
width: Math.max(1, Math.round(cssSize.width * ratio)),
|
|
13
|
+
height: Math.max(1, Math.round(cssSize.height * ratio))
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The element's size in CSS pixels as laid out on the page, transforms included, so that it is
|
|
18
|
+
* measured as the pointer positions on it are.
|
|
19
|
+
*/
|
|
20
|
+
function cssSizeOf(element) {
|
|
21
|
+
const { width, height } = element.getBoundingClientRect();
|
|
22
|
+
return {
|
|
23
|
+
width,
|
|
24
|
+
height
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Keeps the renderer's drawing buffer matched to the canvas's layout size, the screen's pixel
|
|
29
|
+
* ratio and the picture quality.
|
|
30
|
+
*/
|
|
31
|
+
var DrawingBufferFit = class {
|
|
32
|
+
canvas;
|
|
33
|
+
renderer;
|
|
34
|
+
observer;
|
|
35
|
+
ratioWatch = new AbortController();
|
|
36
|
+
quality = DEFAULT_PICTURE_QUALITY;
|
|
37
|
+
constructor(canvas, renderer) {
|
|
38
|
+
this.canvas = canvas;
|
|
39
|
+
this.renderer = renderer;
|
|
40
|
+
this.observer = new ResizeObserver(() => {
|
|
41
|
+
this.fit();
|
|
42
|
+
});
|
|
43
|
+
this.observer.observe(canvas);
|
|
44
|
+
this.watchPixelRatio();
|
|
45
|
+
this.fit();
|
|
46
|
+
}
|
|
47
|
+
setQuality(quality) {
|
|
48
|
+
this.quality = quality;
|
|
49
|
+
this.fit();
|
|
50
|
+
}
|
|
51
|
+
dispose() {
|
|
52
|
+
this.observer.disconnect();
|
|
53
|
+
this.ratioWatch.abort();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A window moved to a screen of another pixel ratio keeps its layout size, so the resize
|
|
57
|
+
* observer stays quiet: a query for the ratio it has now says when that changes.
|
|
58
|
+
*/
|
|
59
|
+
watchPixelRatio() {
|
|
60
|
+
const query = globalThis.matchMedia(`(resolution: ${globalThis.devicePixelRatio}dppx)`);
|
|
61
|
+
const onChange = () => {
|
|
62
|
+
this.fit();
|
|
63
|
+
this.watchPixelRatio();
|
|
64
|
+
};
|
|
65
|
+
query.addEventListener("change", onChange, {
|
|
66
|
+
once: true,
|
|
67
|
+
signal: this.ratioWatch.signal
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
fit() {
|
|
71
|
+
const size = drawingBufferSizeFor(cssSizeOf(this.canvas), globalThis.devicePixelRatio, this.quality);
|
|
72
|
+
if (size.width === this.canvas.width && size.height === this.canvas.height) return;
|
|
73
|
+
this.renderer.resize(size);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
77
|
+
export { DrawingBufferFit, cssSizeOf, drawingBufferSizeFor };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//#region ../../packages/player/src/player/FrameLoop.ts
|
|
2
|
+
var ANIMATION_FRAMES = {
|
|
3
|
+
request: (callback) => requestAnimationFrame(callback),
|
|
4
|
+
cancel: (handle) => {
|
|
5
|
+
cancelAnimationFrame(handle);
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Calls `tick` once per animation frame between {@link start} and {@link stop}.
|
|
10
|
+
*/
|
|
11
|
+
var FrameLoop = class {
|
|
12
|
+
tick;
|
|
13
|
+
scheduler;
|
|
14
|
+
isActive = false;
|
|
15
|
+
handle;
|
|
16
|
+
constructor(tick, scheduler = ANIMATION_FRAMES) {
|
|
17
|
+
this.tick = tick;
|
|
18
|
+
this.scheduler = scheduler;
|
|
19
|
+
}
|
|
20
|
+
start() {
|
|
21
|
+
if (this.isActive) return;
|
|
22
|
+
this.isActive = true;
|
|
23
|
+
this.schedule();
|
|
24
|
+
}
|
|
25
|
+
stop() {
|
|
26
|
+
this.isActive = false;
|
|
27
|
+
if (this.handle === void 0) return;
|
|
28
|
+
this.scheduler.cancel(this.handle);
|
|
29
|
+
this.handle = void 0;
|
|
30
|
+
}
|
|
31
|
+
schedule() {
|
|
32
|
+
this.handle = this.scheduler.request(() => {
|
|
33
|
+
this.handle = void 0;
|
|
34
|
+
this.tick();
|
|
35
|
+
if (this.isActive) this.schedule();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
export { FrameLoop };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { DEFAULT_STABILIZATION_MODE } from "../../../core/src/domain/motion/stabilization/Stabilizer.js";
|
|
2
|
+
import { DEFAULT_PICTURE_QUALITY } from "../../../core/src/domain/view/PictureQuality.js";
|
|
3
|
+
import "../../../core/src/index.js";
|
|
4
|
+
//#region ../../packages/player/src/player/PictureSettings.ts
|
|
5
|
+
/**
|
|
6
|
+
* The settings that shape the picture beyond the view: stabilization, exposure matching and
|
|
7
|
+
* quality, kept across loads, applied to whichever pipeline is attached, announced when they
|
|
8
|
+
* change.
|
|
9
|
+
*/
|
|
10
|
+
var PictureSettings = class {
|
|
11
|
+
events;
|
|
12
|
+
mode = DEFAULT_STABILIZATION_MODE;
|
|
13
|
+
isMatching = true;
|
|
14
|
+
qualityValue = DEFAULT_PICTURE_QUALITY;
|
|
15
|
+
target;
|
|
16
|
+
constructor(events) {
|
|
17
|
+
this.events = events;
|
|
18
|
+
}
|
|
19
|
+
get stabilization() {
|
|
20
|
+
return this.mode;
|
|
21
|
+
}
|
|
22
|
+
get quality() {
|
|
23
|
+
return this.qualityValue;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The pipeline of the loaded recording, or nothing between loads.
|
|
27
|
+
*/
|
|
28
|
+
attach(target) {
|
|
29
|
+
this.target = target;
|
|
30
|
+
target?.setStabilization(this.mode);
|
|
31
|
+
target?.setGainMatching(this.isMatching);
|
|
32
|
+
target?.setQuality(this.qualityValue);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The mode already in effect changes nothing: a stateful mode such as Follow keeps what it has
|
|
36
|
+
* smoothed so far instead of starting over.
|
|
37
|
+
*/
|
|
38
|
+
setStabilization(mode) {
|
|
39
|
+
if (mode === this.mode) return;
|
|
40
|
+
this.mode = mode;
|
|
41
|
+
this.target?.setStabilization(mode);
|
|
42
|
+
this.events.emit("stabilizationchange", mode);
|
|
43
|
+
}
|
|
44
|
+
setGainMatching(isEnabled) {
|
|
45
|
+
this.isMatching = isEnabled;
|
|
46
|
+
this.target?.setGainMatching(isEnabled);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The quality already in effect changes nothing: applying it again would upload the standing
|
|
50
|
+
* frames once more for the same picture.
|
|
51
|
+
*/
|
|
52
|
+
setQuality(quality) {
|
|
53
|
+
if (quality === this.qualityValue) return;
|
|
54
|
+
this.qualityValue = quality;
|
|
55
|
+
this.target?.setQuality(quality);
|
|
56
|
+
this.events.emit("qualitychange", quality);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { PictureSettings };
|