@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.
Files changed (228) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +216 -0
  4. package/dist/define.d.ts +3 -0
  5. package/dist/define.js +4 -0
  6. package/dist/index.d.ts +959 -0
  7. package/dist/index.js +13 -0
  8. package/dist/packages/adapters/blob/src/BlobRandomAccessSource.js +37 -0
  9. package/dist/packages/adapters/blob/src/index.js +2 -0
  10. package/dist/packages/adapters/fetch/src/HttpRangeSource.js +194 -0
  11. package/dist/packages/adapters/fetch/src/HttpResourceLocator.js +35 -0
  12. package/dist/packages/adapters/fetch/src/httpRequest.js +126 -0
  13. package/dist/packages/adapters/fetch/src/index.js +3 -0
  14. package/dist/packages/adapters/mediabunny/src/MediabunnyAudioSegments.js +133 -0
  15. package/dist/packages/adapters/mediabunny/src/MediabunnyDemuxer.js +63 -0
  16. package/dist/packages/adapters/mediabunny/src/MediabunnyVideoTrackReader.js +84 -0
  17. package/dist/packages/adapters/mediabunny/src/SegmentChannel.js +84 -0
  18. package/dist/packages/adapters/mediabunny/src/bufferSources.js +12 -0
  19. package/dist/packages/adapters/mediabunny/src/index.js +2 -0
  20. package/dist/packages/adapters/mse-audio/src/MediaSourceAudioClock.js +139 -0
  21. package/dist/packages/adapters/mse-audio/src/SourceBufferFeeder.js +174 -0
  22. package/dist/packages/adapters/mse-audio/src/events.js +26 -0
  23. package/dist/packages/adapters/mse-audio/src/index.js +2 -0
  24. package/dist/packages/adapters/mse-audio/src/mediaSourceSupport.js +82 -0
  25. package/dist/packages/adapters/three/src/ThreeFrameRenderer.js +274 -0
  26. package/dist/packages/adapters/three/src/compileAndProve.js +14 -0
  27. package/dist/packages/adapters/three/src/fullscreenPass.js +52 -0
  28. package/dist/packages/adapters/three/src/index.js +2 -0
  29. package/dist/packages/adapters/three/src/lensTextures.js +25 -0
  30. package/dist/packages/adapters/three/src/pictureMaterials.js +44 -0
  31. package/dist/packages/adapters/three/src/renderInto.js +15 -0
  32. package/dist/packages/adapters/three/src/rendererUniforms.js +157 -0
  33. package/dist/packages/adapters/three/src/samplingStrategies.js +26 -0
  34. package/dist/packages/adapters/three/src/seamMeter/SeamMeterPass.js +79 -0
  35. package/dist/packages/adapters/three/src/seamMeter/rowMeans.js +38 -0
  36. package/dist/packages/adapters/three/src/shaderPrograms.js +66 -0
  37. package/dist/packages/adapters/three/src/shaders/analysis.frag.js +4 -0
  38. package/dist/packages/adapters/three/src/shaders/equirectangularRays.js +4 -0
  39. package/dist/packages/adapters/three/src/shaders/fixedJoin.js +4 -0
  40. package/dist/packages/adapters/three/src/shaders/fullscreen.vert.js +4 -0
  41. package/dist/packages/adapters/three/src/shaders/header.js +4 -0
  42. package/dist/packages/adapters/three/src/shaders/lensModels.js +4 -0
  43. package/dist/packages/adapters/three/src/shaders/lensSampling.js +4 -0
  44. package/dist/packages/adapters/three/src/shaders/lensTextures.js +4 -0
  45. package/dist/packages/adapters/three/src/shaders/rawLenses.frag.js +4 -0
  46. package/dist/packages/adapters/three/src/shaders/rectilinearRays.js +4 -0
  47. package/dist/packages/adapters/three/src/shaders/screenAreas.js +4 -0
  48. package/dist/packages/adapters/three/src/shaders/stitch.frag.js +4 -0
  49. package/dist/packages/adapters/three/src/webglRenderer.js +37 -0
  50. package/dist/packages/adapters/webcodecs/src/WebCodecsVideoDecoderPort.js +135 -0
  51. package/dist/packages/adapters/webcodecs/src/index.js +2 -0
  52. package/dist/packages/core/src/application/gainMatching/GainMatching.js +66 -0
  53. package/dist/packages/core/src/application/gainMatching/GainMatchingFrameSink.js +62 -0
  54. package/dist/packages/core/src/application/playback/ClockWatch.js +76 -0
  55. package/dist/packages/core/src/application/playback/DecodePipeline.js +188 -0
  56. package/dist/packages/core/src/application/playback/DecodeRun.js +93 -0
  57. package/dist/packages/core/src/application/playback/FramePairQueue.js +93 -0
  58. package/dist/packages/core/src/application/playback/FramePairer.js +60 -0
  59. package/dist/packages/core/src/application/playback/PlaybackSession.js +417 -0
  60. package/dist/packages/core/src/application/playback/SeekOrder.js +36 -0
  61. package/dist/packages/core/src/application/playback/SessionLifecycle.js +42 -0
  62. package/dist/packages/core/src/application/playback/StartGate.js +55 -0
  63. package/dist/packages/core/src/application/playback/TimeUpdates.js +31 -0
  64. package/dist/packages/core/src/application/playback/WallClock.js +46 -0
  65. package/dist/packages/core/src/application/playback/keyframeTimeAt.js +15 -0
  66. package/dist/packages/core/src/application/playback/probeDecoding.js +168 -0
  67. package/dist/packages/core/src/application/recording/frameTimesOf.js +22 -0
  68. package/dist/packages/core/src/application/recording/inspectLayout.js +21 -0
  69. package/dist/packages/core/src/application/recording/inspectRecording.js +124 -0
  70. package/dist/packages/core/src/application/recording/locateOtherLensFile.js +18 -0
  71. package/dist/packages/core/src/application/recording/motionOf.js +39 -0
  72. package/dist/packages/core/src/application/recording/readRecording.js +31 -0
  73. package/dist/packages/core/src/application/recording/timeRecording.js +57 -0
  74. package/dist/packages/core/src/application/stabilization/StabilizingFrameSink.js +31 -0
  75. package/dist/packages/core/src/domain/format/boxes/BoxLayout.js +7 -0
  76. package/dist/packages/core/src/domain/format/boxes/boxConstants.js +16 -0
  77. package/dist/packages/core/src/domain/format/boxes/scanBoxes.js +59 -0
  78. package/dist/packages/core/src/domain/format/calibration/CalibrationVersion.js +13 -0
  79. package/dist/packages/core/src/domain/format/calibration/layouts/CalibrationStringLayout.js +34 -0
  80. package/dist/packages/core/src/domain/format/calibration/layouts/LegacyCalibrationLayout.js +44 -0
  81. package/dist/packages/core/src/domain/format/calibration/layouts/MeiCalibrationLayout.js +45 -0
  82. package/dist/packages/core/src/domain/format/calibration/layouts/PolynomialCalibrationLayout.js +44 -0
  83. package/dist/packages/core/src/domain/format/calibration/offsetTokens.js +65 -0
  84. package/dist/packages/core/src/domain/format/calibration/parseOffsetString.js +52 -0
  85. package/dist/packages/core/src/domain/format/calibration/selectCalibration.js +46 -0
  86. package/dist/packages/core/src/domain/format/captureOrigin.js +20 -0
  87. package/dist/packages/core/src/domain/format/constants.js +33 -0
  88. package/dist/packages/core/src/domain/format/info/infoFields.js +110 -0
  89. package/dist/packages/core/src/domain/format/info/parseInfoRecord.js +90 -0
  90. package/dist/packages/core/src/domain/format/info/readInfoRecord.js +14 -0
  91. package/dist/packages/core/src/domain/format/layout/detectLensLayout.js +122 -0
  92. package/dist/packages/core/src/domain/format/naming/RecordingFileName.js +67 -0
  93. package/dist/packages/core/src/domain/format/records/TrailerRecords.js +83 -0
  94. package/dist/packages/core/src/domain/format/records/exposure/parseExposureRecord.js +48 -0
  95. package/dist/packages/core/src/domain/format/records/gyro/FloatGyroSampleLayout.js +39 -0
  96. package/dist/packages/core/src/domain/format/records/gyro/RawGyroSampleLayout.js +55 -0
  97. package/dist/packages/core/src/domain/format/records/gyro/SampleColumns.js +82 -0
  98. package/dist/packages/core/src/domain/format/records/gyro/gyroLayouts.js +12 -0
  99. package/dist/packages/core/src/domain/format/records/gyro/parseGyroRecord.js +129 -0
  100. package/dist/packages/core/src/domain/format/trailer/RecordHeader.js +23 -0
  101. package/dist/packages/core/src/domain/format/trailer/Trailer.js +23 -0
  102. package/dist/packages/core/src/domain/format/trailer/TrailerFooter.js +27 -0
  103. package/dist/packages/core/src/domain/format/trailer/locateRecords.js +80 -0
  104. package/dist/packages/core/src/domain/format/trailer/parseRecordIndex.js +28 -0
  105. package/dist/packages/core/src/domain/format/trailer/readTrailer.js +32 -0
  106. package/dist/packages/core/src/domain/motion/exposure/ExposureRecord.js +53 -0
  107. package/dist/packages/core/src/domain/motion/gyro/GyroTrack.js +60 -0
  108. package/dist/packages/core/src/domain/motion/gyro/medianStep.js +11 -0
  109. package/dist/packages/core/src/domain/motion/gyro/repairedTimeline.js +101 -0
  110. package/dist/packages/core/src/domain/motion/imu/ImuFrame.js +112 -0
  111. package/dist/packages/core/src/domain/motion/orientation/OrientationTrack.js +146 -0
  112. package/dist/packages/core/src/domain/motion/orientation/estimateGyroBias.js +64 -0
  113. package/dist/packages/core/src/domain/motion/orientation/gravity.js +97 -0
  114. package/dist/packages/core/src/domain/motion/stabilization/Stabilizer.js +13 -0
  115. package/dist/packages/core/src/domain/motion/stabilization/stabilizers.js +86 -0
  116. package/dist/packages/core/src/domain/motion/timing/CaptureClock.js +41 -0
  117. package/dist/packages/core/src/domain/motion/timing/FrameTimes.js +92 -0
  118. package/dist/packages/core/src/domain/motion/timing/frameTimeSources.js +61 -0
  119. package/dist/packages/core/src/domain/motion/timing/resolveFrameTimes.js +68 -0
  120. package/dist/packages/core/src/domain/optics/EquidistantModel.js +39 -0
  121. package/dist/packages/core/src/domain/optics/MeiModel.js +45 -0
  122. package/dist/packages/core/src/domain/optics/PolynomialModel.js +44 -0
  123. package/dist/packages/core/src/domain/optics/gainMatch.js +62 -0
  124. package/dist/packages/core/src/domain/optics/lensGeometry.js +18 -0
  125. package/dist/packages/core/src/domain/optics/lensPose.js +35 -0
  126. package/dist/packages/core/src/domain/optics/opticsConstants.js +5 -0
  127. package/dist/packages/core/src/domain/playback/PlayerState.js +83 -0
  128. package/dist/packages/core/src/domain/stitching/LensLayout.js +21 -0
  129. package/dist/packages/core/src/domain/stitching/StitchingSetup.js +78 -0
  130. package/dist/packages/core/src/domain/stitching/seamDisparity.js +4 -0
  131. package/dist/packages/core/src/domain/stitching/seamDisparityField.js +5 -0
  132. package/dist/packages/core/src/domain/stitching/seamJoin.js +16 -0
  133. package/dist/packages/core/src/domain/stitching/seamMismatch.js +1 -0
  134. package/dist/packages/core/src/domain/stitching/seamRing.js +4 -0
  135. package/dist/packages/core/src/domain/stitching/seamStrip.js +26 -0
  136. package/dist/packages/core/src/domain/view/Framing.js +31 -0
  137. package/dist/packages/core/src/domain/view/PictureQuality.js +26 -0
  138. package/dist/packages/core/src/domain/view/ViewMode.js +9 -0
  139. package/dist/packages/core/src/domain/view/ViewState.js +48 -0
  140. package/dist/packages/core/src/domain/view/lensTilesView.js +63 -0
  141. package/dist/packages/core/src/domain/view/magnification.js +103 -0
  142. package/dist/packages/core/src/domain/view/normalView.js +29 -0
  143. package/dist/packages/core/src/domain/view/panoramaView.js +99 -0
  144. package/dist/packages/core/src/domain/view/rectilinear.js +40 -0
  145. package/dist/packages/core/src/domain/view/screenLayout.js +113 -0
  146. package/dist/packages/core/src/domain/view/viewGestures.js +98 -0
  147. package/dist/packages/core/src/domain/view/viewModes.js +14 -0
  148. package/dist/packages/core/src/index.js +59 -0
  149. package/dist/packages/core/src/ports/FramePair.js +6 -0
  150. package/dist/packages/core/src/shared/async/Deferred.js +42 -0
  151. package/dist/packages/core/src/shared/async/RunStop.js +40 -0
  152. package/dist/packages/core/src/shared/binary/ByteRange.js +38 -0
  153. package/dist/packages/core/src/shared/binary/ByteReader.js +77 -0
  154. package/dist/packages/core/src/shared/errors/GyroViewError.js +81 -0
  155. package/dist/packages/core/src/shared/errors/reportLater.js +11 -0
  156. package/dist/packages/core/src/shared/events/Outbox.js +68 -0
  157. package/dist/packages/core/src/shared/events/TypedEmitter.js +55 -0
  158. package/dist/packages/core/src/shared/keysOf.js +10 -0
  159. package/dist/packages/core/src/shared/lazy.js +11 -0
  160. package/dist/packages/core/src/shared/math/Matrix3.js +93 -0
  161. package/dist/packages/core/src/shared/math/Quaternion.js +133 -0
  162. package/dist/packages/core/src/shared/math/Vector3.js +54 -0
  163. package/dist/packages/core/src/shared/math/clamp.js +9 -0
  164. package/dist/packages/core/src/shared/protobuf/ProtobufMessage.js +157 -0
  165. package/dist/packages/core/src/shared/text/urlPath.js +31 -0
  166. package/dist/packages/core/src/shared/text/utf8.js +12 -0
  167. package/dist/packages/core/src/shared/units/angle.js +22 -0
  168. package/dist/packages/core/src/shared/units/time.js +13 -0
  169. package/dist/packages/player/src/PlayerSource.js +15 -0
  170. package/dist/packages/player/src/browserPlayer.js +18 -0
  171. package/dist/packages/player/src/choices.js +25 -0
  172. package/dist/packages/player/src/composition/Disposables.js +31 -0
  173. package/dist/packages/player/src/composition/browserPorts.js +46 -0
  174. package/dist/packages/player/src/composition/buildPipeline.js +153 -0
  175. package/dist/packages/player/src/composition/ensureDecodable.js +63 -0
  176. package/dist/packages/player/src/composition/openInputs.js +179 -0
  177. package/dist/packages/player/src/composition/openRecording.js +42 -0
  178. package/dist/packages/player/src/controls/ChoiceMenu.js +113 -0
  179. package/dist/packages/player/src/controls/PictureMenus.js +47 -0
  180. package/dist/packages/player/src/controls/SeekBar.js +125 -0
  181. package/dist/packages/player/src/controls/SoundControls.js +41 -0
  182. package/dist/packages/player/src/controls/TransportButtons.js +31 -0
  183. package/dist/packages/player/src/controls/ViewGestures.js +136 -0
  184. package/dist/packages/player/src/controls/Wording.js +78 -0
  185. package/dist/packages/player/src/controls/controlParts.js +36 -0
  186. package/dist/packages/player/src/controls/controls.js +4 -0
  187. package/dist/packages/player/src/controls/controlsBar.js +23 -0
  188. package/dist/packages/player/src/controls/controlsMarkup.js +85 -0
  189. package/dist/packages/player/src/controls/customControls.js +59 -0
  190. package/dist/packages/player/src/controls/formatTime.js +19 -0
  191. package/dist/packages/player/src/controls/icons.js +40 -0
  192. package/dist/packages/player/src/controls/keyboard.js +118 -0
  193. package/dist/packages/player/src/controls/messages.js +94 -0
  194. package/dist/packages/player/src/controls/parseMarkup.js +31 -0
  195. package/dist/packages/player/src/controls/viewButtons.js +14 -0
  196. package/dist/packages/player/src/element/ElementLoads.js +119 -0
  197. package/dist/packages/player/src/element/FullscreenToggle.js +39 -0
  198. package/dist/packages/player/src/element/GyroViewElement.js +313 -0
  199. package/dist/packages/player/src/element/IdleWatcher.js +71 -0
  200. package/dist/packages/player/src/element/TypedEventElement.js +22 -0
  201. package/dist/packages/player/src/element/accessibleRegion.js +19 -0
  202. package/dist/packages/player/src/element/attributeNames.js +51 -0
  203. package/dist/packages/player/src/element/attributes.js +101 -0
  204. package/dist/packages/player/src/element/defineGyroView.js +21 -0
  205. package/dist/packages/player/src/element/earlyProperties.js +36 -0
  206. package/dist/packages/player/src/element/elementSource.js +23 -0
  207. package/dist/packages/player/src/element/liveSettings.js +138 -0
  208. package/dist/packages/player/src/element/playbackAttributes.js +53 -0
  209. package/dist/packages/player/src/element/playerEventMirror.js +33 -0
  210. package/dist/packages/player/src/element/reflectedProperties.js +78 -0
  211. package/dist/packages/player/src/element/styles.js +4 -0
  212. package/dist/packages/player/src/element/template.js +47 -0
  213. package/dist/packages/player/src/index.js +10 -0
  214. package/dist/packages/player/src/inspectRecording.js +22 -0
  215. package/dist/packages/player/src/player/DrawingBufferFit.js +77 -0
  216. package/dist/packages/player/src/player/FrameLoop.js +40 -0
  217. package/dist/packages/player/src/player/PictureSettings.js +60 -0
  218. package/dist/packages/player/src/player/Player.js +377 -0
  219. package/dist/packages/player/src/player/PlayerEvents.js +28 -0
  220. package/dist/packages/player/src/player/PlayerPhase.js +21 -0
  221. package/dist/packages/player/src/player/PlayerSound.js +61 -0
  222. package/dist/packages/player/src/player/PlayerView.js +113 -0
  223. package/dist/packages/player/src/player/SessionRelay.js +66 -0
  224. package/dist/packages/player/src/player/ensureFinite.js +26 -0
  225. package/dist/packages/player/src/player/loadRecording.js +65 -0
  226. package/dist/packages/player/src/player/transportEvents.js +29 -0
  227. package/dist/standalone.js +4919 -0
  228. 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 };