@swf2es/player-hosts 0.0.0-stage → 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/LICENSE +202 -0
- package/LICENSE.third-party +759 -0
- package/README.md +43 -2
- package/dist/indexeddb.d.ts +27 -0
- package/dist/indexeddb.d.ts.map +1 -0
- package/dist/indexeddb.js +170 -0
- package/dist/indexeddb.js.map +1 -0
- package/dist/node-worker.d.ts +2 -0
- package/dist/node-worker.d.ts.map +1 -0
- package/dist/node-worker.js +12 -0
- package/dist/node-worker.js.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +43 -0
- package/dist/node.js.map +1 -0
- package/dist/precompiled.d.ts +31 -0
- package/dist/precompiled.d.ts.map +1 -0
- package/dist/precompiled.js +125 -0
- package/dist/precompiled.js.map +1 -0
- package/dist/stage3d.d.ts +13 -0
- package/dist/stage3d.d.ts.map +1 -0
- package/dist/stage3d.js +61 -0
- package/dist/stage3d.js.map +1 -0
- package/dist/thread/codegen/codegen.js +308 -0
- package/dist/thread/codegen/index.js +405 -0
- package/dist/thread/format/abc-names.js +126 -0
- package/dist/thread/format/actions.js +222 -0
- package/dist/thread/format/air-descriptor.js +63 -0
- package/dist/thread/format/api-versions.js +22 -0
- package/dist/thread/format/bitmap.js +199 -0
- package/dist/thread/format/button.js +60 -0
- package/dist/thread/format/compression.js +200 -0
- package/dist/thread/format/display.js +305 -0
- package/dist/thread/format/filters.js +136 -0
- package/dist/thread/format/font.js +168 -0
- package/dist/thread/format/index.js +26 -0
- package/dist/thread/format/pbj.js +484 -0
- package/dist/thread/format/shape.js +411 -0
- package/dist/thread/format/sound.js +91 -0
- package/dist/thread/format/swf.js +163 -0
- package/dist/thread/format/tags.js +58 -0
- package/dist/thread/format/text.js +135 -0
- package/dist/thread/format/zip.js +91 -0
- package/dist/thread/native/audio/binary.js +3 -0
- package/dist/thread/native/audio/index.js +72 -0
- package/dist/thread/native/base64.js +9 -0
- package/dist/thread/native/compress/binary.js +3 -0
- package/dist/thread/native/compress/index.js +145 -0
- package/dist/thread/native/instance.js +49 -0
- package/dist/thread/native/mp3/binary.js +3 -0
- package/dist/thread/native/mp3/index.js +48 -0
- package/dist/thread/native/render/binary.js +3 -0
- package/dist/thread/native/render/bitmap-kernel.js +591 -0
- package/dist/thread/native/render/draw-kernel.js +204 -0
- package/dist/thread/native/render/dxt-encoder.js +94 -0
- package/dist/thread/native/render/index.js +10 -0
- package/dist/thread/native/render/lines.js +122 -0
- package/dist/thread/native/render/module.js +26 -0
- package/dist/thread/native/render/pixel-ops.js +235 -0
- package/dist/thread/native/render/tessellator.js +250 -0
- package/dist/thread/player/avm1/amf.js +507 -0
- package/dist/thread/player/avm1/avm1.js +1304 -0
- package/dist/thread/player/avm1/bindings.js +214 -0
- package/dist/thread/player/avm1/classes.js +75 -0
- package/dist/thread/player/avm1/clips.js +229 -0
- package/dist/thread/player/avm1/compile.js +140 -0
- package/dist/thread/player/avm1/external.js +79 -0
- package/dist/thread/player/avm1/focus.js +278 -0
- package/dist/thread/player/avm1/globals/BitmapData.js +542 -0
- package/dist/thread/player/avm1/globals/Button.js +31 -0
- package/dist/thread/player/avm1/globals/Color.js +115 -0
- package/dist/thread/player/avm1/globals/ExternalInterface.js +310 -0
- package/dist/thread/player/avm1/globals/FileReference.js +217 -0
- package/dist/thread/player/avm1/globals/Key.js +60 -0
- package/dist/thread/player/avm1/globals/LoadVars.js +208 -0
- package/dist/thread/player/avm1/globals/LocalConnection.js +92 -0
- package/dist/thread/player/avm1/globals/MovieClip.js +1070 -0
- package/dist/thread/player/avm1/globals/MovieClipLoader.js +90 -0
- package/dist/thread/player/avm1/globals/NetConnection.js +261 -0
- package/dist/thread/player/avm1/globals/PrintJob.js +37 -0
- package/dist/thread/player/avm1/globals/Selection.js +62 -0
- package/dist/thread/player/avm1/globals/SharedObject.js +245 -0
- package/dist/thread/player/avm1/globals/Sound.js +238 -0
- package/dist/thread/player/avm1/globals/Stage.js +12 -0
- package/dist/thread/player/avm1/globals/StyleSheet.js +205 -0
- package/dist/thread/player/avm1/globals/TextField.js +396 -0
- package/dist/thread/player/avm1/globals/TextFormat.js +194 -0
- package/dist/thread/player/avm1/globals/TextSnapshot.js +88 -0
- package/dist/thread/player/avm1/globals/XML.js +396 -0
- package/dist/thread/player/avm1/globals/XMLNode.js +413 -0
- package/dist/thread/player/avm1/globals/XMLSocket.js +205 -0
- package/dist/thread/player/avm1/globals/drawing.js +202 -0
- package/dist/thread/player/avm1/globals/filters.js +635 -0
- package/dist/thread/player/avm1/globals/geom.js +600 -0
- package/dist/thread/player/avm1/input.js +483 -0
- package/dist/thread/player/avm1/keyboard.js +113 -0
- package/dist/thread/player/avm1/loads.js +352 -0
- package/dist/thread/player/avm1/net.js +219 -0
- package/dist/thread/player/avm1/paths.js +104 -0
- package/dist/thread/player/avm1/pointer.js +512 -0
- package/dist/thread/player/avm1/queue.js +303 -0
- package/dist/thread/player/avm1/sound.js +106 -0
- package/dist/thread/player/avm1/swf.js +141 -0
- package/dist/thread/player/avm1/timers.js +113 -0
- package/dist/thread/player/bitmap/bitmap.js +627 -0
- package/dist/thread/player/bitmap/draw.js +68 -0
- package/dist/thread/player/bitmap/dxt.js +11 -0
- package/dist/thread/player/bitmap/filters.js +656 -0
- package/dist/thread/player/bitmap/images.js +240 -0
- package/dist/thread/player/bitmap/kernel.js +65 -0
- package/dist/thread/player/bitmap/ops.js +1239 -0
- package/dist/thread/player/bitmap/pixel-bender.js +911 -0
- package/dist/thread/player/bitmap/png.js +139 -0
- package/dist/thread/player/bitmap/turbulence.js +89 -0
- package/dist/thread/player/clock.js +182 -0
- package/dist/thread/player/display/bitmapobject.js +25 -0
- package/dist/thread/player/display/bounds.js +520 -0
- package/dist/thread/player/display/buttonobject.js +305 -0
- package/dist/thread/player/display/color.js +40 -0
- package/dist/thread/player/display/container.js +150 -0
- package/dist/thread/player/display/display.js +14 -0
- package/dist/thread/player/display/displayobject.js +664 -0
- package/dist/thread/player/display/drawing.js +613 -0
- package/dist/thread/player/display/filters.js +285 -0
- package/dist/thread/player/display/geometry.js +189 -0
- package/dist/thread/player/display/gradients.js +117 -0
- package/dist/thread/player/display/graphicsdata.js +592 -0
- package/dist/thread/player/display/instantiate.js +71 -0
- package/dist/thread/player/display/matrix3d.js +373 -0
- package/dist/thread/player/display/morph.js +226 -0
- package/dist/thread/player/display/movieclip.js +680 -0
- package/dist/thread/player/display/perspective.js +193 -0
- package/dist/thread/player/display/scale9.js +236 -0
- package/dist/thread/player/display/shapeobject.js +131 -0
- package/dist/thread/player/display/shapes.js +407 -0
- package/dist/thread/player/display/textobjects.js +222 -0
- package/dist/thread/player/display/timeline.js +471 -0
- package/dist/thread/player/display/value-lists.js +40 -0
- package/dist/thread/player/display/videoobject.js +6 -0
- package/dist/thread/player/display/walk.js +127 -0
- package/dist/thread/player/files.js +334 -0
- package/dist/thread/player/hosts.js +207 -0
- package/dist/thread/player/input/avm1.js +82 -0
- package/dist/thread/player/input/context-menu.js +63 -0
- package/dist/thread/player/input/keyboard.js +458 -0
- package/dist/thread/player/input/pointer.js +863 -0
- package/dist/thread/player/input/text-editor.js +319 -0
- package/dist/thread/player/input/touch.js +209 -0
- package/dist/thread/player/localconnection.js +90 -0
- package/dist/thread/player/media/audio.js +376 -0
- package/dist/thread/player/media/dynamic-sound.js +90 -0
- package/dist/thread/player/media/extract.js +135 -0
- package/dist/thread/player/media/mp3.js +152 -0
- package/dist/thread/player/media/sounds.js +507 -0
- package/dist/thread/player/media/streaming-audio.js +133 -0
- package/dist/thread/player/player.js +616 -0
- package/dist/thread/player/playerglobal/air/net/WebSocket.js +250 -0
- package/dist/thread/player/playerglobal/air-library.js +8 -0
- package/dist/thread/player/playerglobal/flash/accessibility/Accessibility.js +21 -0
- package/dist/thread/player/playerglobal/flash/crypto/generateRandomBytes.js +32 -0
- package/dist/thread/player/playerglobal/flash/data/EncryptedLocalStore.js +61 -0
- package/dist/thread/player/playerglobal/flash/desktop/Clipboard.js +173 -0
- package/dist/thread/player/playerglobal/flash/desktop/NativeApplication.js +179 -0
- package/dist/thread/player/playerglobal/flash/display/AVM1Movie.js +19 -0
- package/dist/thread/player/playerglobal/flash/display/Bitmap.js +58 -0
- package/dist/thread/player/playerglobal/flash/display/BitmapData.js +633 -0
- package/dist/thread/player/playerglobal/flash/display/DisplayObject.js +614 -0
- package/dist/thread/player/playerglobal/flash/display/DisplayObjectContainer.js +224 -0
- package/dist/thread/player/playerglobal/flash/display/Graphics.js +345 -0
- package/dist/thread/player/playerglobal/flash/display/InteractiveObject.js +87 -0
- package/dist/thread/player/playerglobal/flash/display/Loader.js +79 -0
- package/dist/thread/player/playerglobal/flash/display/LoaderInfo.js +128 -0
- package/dist/thread/player/playerglobal/flash/display/MovieClip.js +194 -0
- package/dist/thread/player/playerglobal/flash/display/NativeWindow.js +245 -0
- package/dist/thread/player/playerglobal/flash/display/Shader.js +26 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderData.js +85 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderInput.js +64 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderJob.js +181 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderParameter.js +23 -0
- package/dist/thread/player/playerglobal/flash/display/Shape.js +13 -0
- package/dist/thread/player/playerglobal/flash/display/SimpleButton.js +103 -0
- package/dist/thread/player/playerglobal/flash/display/Sprite.js +84 -0
- package/dist/thread/player/playerglobal/flash/display/Stage.js +231 -0
- package/dist/thread/player/playerglobal/flash/display/Stage3D.js +54 -0
- package/dist/thread/player/playerglobal/flash/display/shaders.js +228 -0
- package/dist/thread/player/playerglobal/flash/events/Event.js +58 -0
- package/dist/thread/player/playerglobal/flash/events/EventDispatcher.js +103 -0
- package/dist/thread/player/playerglobal/flash/events/GestureEvent.js +34 -0
- package/dist/thread/player/playerglobal/flash/events/HTTPStatusEvent.js +8 -0
- package/dist/thread/player/playerglobal/flash/events/KeyboardEvent.js +51 -0
- package/dist/thread/player/playerglobal/flash/events/MouseEvent.js +59 -0
- package/dist/thread/player/playerglobal/flash/events/PressAndTapGestureEvent.js +30 -0
- package/dist/thread/player/playerglobal/flash/events/TimerEvent.js +16 -0
- package/dist/thread/player/playerglobal/flash/events/TouchEvent.js +45 -0
- package/dist/thread/player/playerglobal/flash/external/ExternalInterface.js +73 -0
- package/dist/thread/player/playerglobal/flash/filesystem/File.js +340 -0
- package/dist/thread/player/playerglobal/flash/filesystem/FileStream.js +453 -0
- package/dist/thread/player/playerglobal/flash/filesystem/paths.js +156 -0
- package/dist/thread/player/playerglobal/flash/filesystem/writes.js +143 -0
- package/dist/thread/player/playerglobal/flash/filters/BevelFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/BitmapFilter.js +205 -0
- package/dist/thread/player/playerglobal/flash/filters/BlurFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/ColorMatrixFilter.js +11 -0
- package/dist/thread/player/playerglobal/flash/filters/ConvolutionFilter.js +26 -0
- package/dist/thread/player/playerglobal/flash/filters/DisplacementMapFilter.js +51 -0
- package/dist/thread/player/playerglobal/flash/filters/DropShadowFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/GlowFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/GradientBevelFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/GradientGlowFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/ShaderFilter.js +53 -0
- package/dist/thread/player/playerglobal/flash/geom/Matrix3D.js +361 -0
- package/dist/thread/player/playerglobal/flash/geom/PerspectiveProjection.js +122 -0
- package/dist/thread/player/playerglobal/flash/geom/Transform.js +245 -0
- package/dist/thread/player/playerglobal/flash/geom/Utils3D.js +85 -0
- package/dist/thread/player/playerglobal/flash/globalization/Collator.js +149 -0
- package/dist/thread/player/playerglobal/flash/globalization/CurrencyFormatter.js +272 -0
- package/dist/thread/player/playerglobal/flash/globalization/CurrencyParseResult.js +21 -0
- package/dist/thread/player/playerglobal/flash/globalization/DateTimeFormatter.js +463 -0
- package/dist/thread/player/playerglobal/flash/globalization/LocaleID.js +144 -0
- package/dist/thread/player/playerglobal/flash/globalization/NumberFormatter.js +444 -0
- package/dist/thread/player/playerglobal/flash/globalization/NumberParseResult.js +22 -0
- package/dist/thread/player/playerglobal/flash/globalization/StringTools.js +59 -0
- package/dist/thread/player/playerglobal/flash/globalization/locale.js +190 -0
- package/dist/thread/player/playerglobal/flash/media/Camera.js +89 -0
- package/dist/thread/player/playerglobal/flash/media/Microphone.js +126 -0
- package/dist/thread/player/playerglobal/flash/media/Sound.js +543 -0
- package/dist/thread/player/playerglobal/flash/media/SoundMixer.js +74 -0
- package/dist/thread/player/playerglobal/flash/media/SoundTransform.js +40 -0
- package/dist/thread/player/playerglobal/flash/media/Video.js +43 -0
- package/dist/thread/player/playerglobal/flash/net/FileFilter.js +27 -0
- package/dist/thread/player/playerglobal/flash/net/FileReference.js +197 -0
- package/dist/thread/player/playerglobal/flash/net/LocalConnection.js +167 -0
- package/dist/thread/player/playerglobal/flash/net/NetConnection.js +155 -0
- package/dist/thread/player/playerglobal/flash/net/SharedObject.js +299 -0
- package/dist/thread/player/playerglobal/flash/net/Socket.js +282 -0
- package/dist/thread/player/playerglobal/flash/net/URLRequest.js +93 -0
- package/dist/thread/player/playerglobal/flash/net/URLStream.js +146 -0
- package/dist/thread/player/playerglobal/flash/net/XMLSocket.js +14 -0
- package/dist/thread/player/playerglobal/flash/net/local-modern.js +142 -0
- package/dist/thread/player/playerglobal/flash/net/local-values.js +217 -0
- package/dist/thread/player/playerglobal/flash/net/navigateToURL.js +29 -0
- package/dist/thread/player/playerglobal/flash/profiler/Telemetry.js +25 -0
- package/dist/thread/player/playerglobal/flash/sensors/Accelerometer.js +12 -0
- package/dist/thread/player/playerglobal/flash/system/ApplicationDomain.js +69 -0
- package/dist/thread/player/playerglobal/flash/system/Capabilities.js +163 -0
- package/dist/thread/player/playerglobal/flash/system/FSCommandHost.js +17 -0
- package/dist/thread/player/playerglobal/flash/system/Security.js +46 -0
- package/dist/thread/player/playerglobal/flash/system/SecurityDomain.js +21 -0
- package/dist/thread/player/playerglobal/flash/system/System.js +73 -0
- package/dist/thread/player/playerglobal/flash/system/Worker.js +112 -0
- package/dist/thread/player/playerglobal/flash/text/Font.js +95 -0
- package/dist/thread/player/playerglobal/flash/text/StaticText.js +16 -0
- package/dist/thread/player/playerglobal/flash/text/StyleSheet.js +65 -0
- package/dist/thread/player/playerglobal/flash/text/TextField.js +707 -0
- package/dist/thread/player/playerglobal/flash/text/TextRenderer.js +77 -0
- package/dist/thread/player/playerglobal/flash/text/engine/FontDescription.js +141 -0
- package/dist/thread/player/playerglobal/flash/text/engine/TabStop.js +46 -0
- package/dist/thread/player/playerglobal/flash/trace/Trace.js +17 -0
- package/dist/thread/player/playerglobal/flash/ui/ContextMenu.js +17 -0
- package/dist/thread/player/playerglobal/flash/ui/GameInput.js +19 -0
- package/dist/thread/player/playerglobal/flash/ui/Keyboard.js +27 -0
- package/dist/thread/player/playerglobal/flash/ui/Mouse.js +127 -0
- package/dist/thread/player/playerglobal/flash/ui/Multitouch.js +46 -0
- package/dist/thread/player/playerglobal/flash/utils/ByteArray.js +155 -0
- package/dist/thread/player/playerglobal/flash/utils/Timer.js +25 -0
- package/dist/thread/player/playerglobal/flash/xml/XMLDocument.js +74 -0
- package/dist/thread/player/playerglobal/index.js +224 -0
- package/dist/thread/player/playerglobal/libraries.js +10 -0
- package/dist/thread/player/playerglobal/playerglobal-library.js +22 -0
- package/dist/thread/player/playerglobal/toplevel.js +122 -0
- package/dist/thread/player/scripting/clipboard.js +146 -0
- package/dist/thread/player/scripting/code.js +900 -0
- package/dist/thread/player/scripting/evaluate.js +144 -0
- package/dist/thread/player/scripting/events.js +172 -0
- package/dist/thread/player/scripting/handover.js +182 -0
- package/dist/thread/player/scripting/lazy.js +38 -0
- package/dist/thread/player/scripting/lifecycle.js +272 -0
- package/dist/thread/player/scripting/loads.js +860 -0
- package/dist/thread/player/scripting/sha256.js +95 -0
- package/dist/thread/player/scripting/symbols.js +348 -0
- package/dist/thread/player/scripting/timers.js +434 -0
- package/dist/thread/player/scripting/workers.js +923 -0
- package/dist/thread/player/scripting.js +1018 -0
- package/dist/thread/player/stage.js +4 -0
- package/dist/thread/player/text/csm.js +113 -0
- package/dist/thread/player/text/css.js +167 -0
- package/dist/thread/player/text/fonts.js +97 -0
- package/dist/thread/player/text/layout.js +393 -0
- package/dist/thread/player/text/static.js +109 -0
- package/dist/thread/player/text/text.js +431 -0
- package/dist/thread/player/workers/thread.js +159 -0
- package/dist/thread/player/workers/wire.js +198 -0
- package/dist/thread/player-hosts/web-worker.js +19 -0
- package/dist/thread/runtime/avm1/activation.js +89 -0
- package/dist/thread/runtime/avm1/case.js +249 -0
- package/dist/thread/runtime/avm1/clips.js +334 -0
- package/dist/thread/runtime/avm1/control.js +280 -0
- package/dist/thread/runtime/avm1/errors.js +50 -0
- package/dist/thread/runtime/avm1/functions.js +249 -0
- package/dist/thread/runtime/avm1/globals/array.js +549 -0
- package/dist/thread/runtime/avm1/globals/broadcaster.js +131 -0
- package/dist/thread/runtime/avm1/globals/date.js +436 -0
- package/dist/thread/runtime/avm1/globals/global.js +344 -0
- package/dist/thread/runtime/avm1/globals/math.js +139 -0
- package/dist/thread/runtime/avm1/globals/number.js +93 -0
- package/dist/thread/runtime/avm1/globals/string.js +201 -0
- package/dist/thread/runtime/avm1/globals/timers.js +129 -0
- package/dist/thread/runtime/avm1/host.js +5 -0
- package/dist/thread/runtime/avm1/index.js +14 -0
- package/dist/thread/runtime/avm1/inheritance.js +132 -0
- package/dist/thread/runtime/avm1/numbers.js +298 -0
- package/dist/thread/runtime/avm1/objects.js +896 -0
- package/dist/thread/runtime/avm1/operators.js +170 -0
- package/dist/thread/runtime/avm1/realm.js +529 -0
- package/dist/thread/runtime/avm1/runtime.js +882 -0
- package/dist/thread/runtime/avm1/scope.js +385 -0
- package/dist/thread/runtime/avm1/urls.js +180 -0
- package/dist/thread/runtime/avm1/values.js +97 -0
- package/dist/thread/runtime/avm2/amf-classes.js +66 -0
- package/dist/thread/runtime/avm2/amf.js +801 -0
- package/dist/thread/runtime/avm2/array-conversion.js +100 -0
- package/dist/thread/runtime/avm2/builtin-library.js +21 -0
- package/dist/thread/runtime/avm2/cache-fill.js +86 -0
- package/dist/thread/runtime/avm2/classes.js +211 -0
- package/dist/thread/runtime/avm2/definitions.js +69 -0
- package/dist/thread/runtime/avm2/descriptors.js +5 -0
- package/dist/thread/runtime/avm2/dictionary-keys.js +295 -0
- package/dist/thread/runtime/avm2/domain-memory.js +75 -0
- package/dist/thread/runtime/avm2/domain.js +280 -0
- package/dist/thread/runtime/avm2/dynamic-properties.js +182 -0
- package/dist/thread/runtime/avm2/enumeration.js +393 -0
- package/dist/thread/runtime/avm2/errors.js +45 -0
- package/dist/thread/runtime/avm2/float-library.js +66 -0
- package/dist/thread/runtime/avm2/float.js +26 -0
- package/dist/thread/runtime/avm2/hooks.js +19 -0
- package/dist/thread/runtime/avm2/index.js +38 -0
- package/dist/thread/runtime/avm2/messages.js +177 -0
- package/dist/thread/runtime/avm2/method-factories.js +95 -0
- package/dist/thread/runtime/avm2/modules.js +105 -0
- package/dist/thread/runtime/avm2/names.js +248 -0
- package/dist/thread/runtime/avm2/natives/aliases.js +47 -0
- package/dist/thread/runtime/avm2/natives/array.js +390 -0
- package/dist/thread/runtime/avm2/natives/bytearray.js +1227 -0
- package/dist/thread/runtime/avm2/natives/case.js +88 -0
- package/dist/thread/runtime/avm2/natives/concurrent.js +199 -0
- package/dist/thread/runtime/avm2/natives/date.js +581 -0
- package/dist/thread/runtime/avm2/natives/define.js +130 -0
- package/dist/thread/runtime/avm2/natives/describe.js +351 -0
- package/dist/thread/runtime/avm2/natives/dictionary.js +12 -0
- package/dist/thread/runtime/avm2/natives/float-vector.js +81 -0
- package/dist/thread/runtime/avm2/natives/float.js +96 -0
- package/dist/thread/runtime/avm2/natives/index.js +64 -0
- package/dist/thread/runtime/avm2/natives/json.js +514 -0
- package/dist/thread/runtime/avm2/natives/number.js +162 -0
- package/dist/thread/runtime/avm2/natives/object.js +237 -0
- package/dist/thread/runtime/avm2/natives/proxy.js +75 -0
- package/dist/thread/runtime/avm2/natives/regexp.js +485 -0
- package/dist/thread/runtime/avm2/natives/shell-workers.js +404 -0
- package/dist/thread/runtime/avm2/natives/shell.js +557 -0
- package/dist/thread/runtime/avm2/natives/sort.js +377 -0
- package/dist/thread/runtime/avm2/natives/string.js +132 -0
- package/dist/thread/runtime/avm2/natives/sync.js +821 -0
- package/dist/thread/runtime/avm2/natives/toplevel.js +139 -0
- package/dist/thread/runtime/avm2/natives/vector-elements.js +46 -0
- package/dist/thread/runtime/avm2/natives/vector.js +406 -0
- package/dist/thread/runtime/avm2/natives/xml/access.js +633 -0
- package/dist/thread/runtime/avm2/natives/xml/build.js +291 -0
- package/dist/thread/runtime/avm2/natives/xml/chars.js +112 -0
- package/dist/thread/runtime/avm2/natives/xml/escape.js +38 -0
- package/dist/thread/runtime/avm2/natives/xml/names.js +204 -0
- package/dist/thread/runtime/avm2/natives/xml/node.js +272 -0
- package/dist/thread/runtime/avm2/natives/xml/operators.js +69 -0
- package/dist/thread/runtime/avm2/natives/xml/parser.js +356 -0
- package/dist/thread/runtime/avm2/natives/xml/strings.js +191 -0
- package/dist/thread/runtime/avm2/natives/xml/values.js +122 -0
- package/dist/thread/runtime/avm2/natives/xml/xml.js +645 -0
- package/dist/thread/runtime/avm2/number-strings.js +110 -0
- package/dist/thread/runtime/avm2/numbers.js +558 -0
- package/dist/thread/runtime/avm2/options.js +16 -0
- package/dist/thread/runtime/avm2/player-messages.js +550 -0
- package/dist/thread/runtime/avm2/property-cache.js +135 -0
- package/dist/thread/runtime/avm2/runtime.js +2644 -0
- package/dist/thread/runtime/avm2/traits.js +509 -0
- package/dist/thread/runtime/index.js +7 -0
- package/dist/web-worker.d.ts +2 -0
- package/dist/web-worker.d.ts.map +1 -0
- package/dist/web-worker.js +20 -0
- package/dist/web-worker.js.map +1 -0
- package/dist/websocket.d.ts +4 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +27 -0
- package/dist/websocket.js.map +1 -0
- package/dist/workers.d.ts +35 -0
- package/dist/workers.d.ts.map +1 -0
- package/dist/workers.js +171 -0
- package/dist/workers.js.map +1 -0
- package/package.json +62 -3
- package/src/indexeddb.ts +227 -0
- package/src/node-worker.ts +13 -0
- package/src/node.ts +49 -0
- package/src/precompiled.ts +166 -0
- package/src/stage3d.ts +76 -0
- package/src/web-worker.ts +24 -0
- package/src/websocket.ts +32 -0
- package/src/workers.ts +255 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// What Flash reads of MP3 bytes before it decodes them: its frames, by
|
|
2
|
+
// their headers, past ID3v2 tags and other bytes between them. Flash
|
|
3
|
+
// counts a frame the bytes cut short in a sound's length but decodes only
|
|
4
|
+
// whole frames, and decodes a Xing, Info or VBRI frame as a frame of
|
|
5
|
+
// silence like any other (adl, the sound-extract case), where a browser's
|
|
6
|
+
// decoder reads it to trim the encoder's delay and padding. A header is
|
|
7
|
+
// trusted as the start of a run only with the next two frames' headers
|
|
8
|
+
// where it says they are, as decoders find their way into a stream, so
|
|
9
|
+
// that bytes that happen to look like one, in a tag or another format,
|
|
10
|
+
// are passed over.
|
|
11
|
+
/** Kilobits a second by bitrate index: MPEG-1 Layer III, then MPEG-2 and 2.5. */
|
|
12
|
+
const BITRATES = [
|
|
13
|
+
[0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320],
|
|
14
|
+
[0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
|
|
15
|
+
];
|
|
16
|
+
/** Rates by index for MPEG-2.5, (reserved), MPEG-2 and MPEG-1, as the version bits number them. */
|
|
17
|
+
const RATES = [[11025, 12000, 8000], [], [22050, 24000, 16000], [44100, 48000, 32000]];
|
|
18
|
+
/** How many headers in a row, the first included, make a run. */
|
|
19
|
+
const RUN = 3;
|
|
20
|
+
function header(bytes, at) {
|
|
21
|
+
if (at + 4 > bytes.length || bytes[at] !== 0xff || (bytes[at + 1] & 0xe0) !== 0xe0) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const version = (bytes[at + 1] >> 3) & 3;
|
|
25
|
+
const layer = (bytes[at + 1] >> 1) & 3;
|
|
26
|
+
const bitrate = bytes[at + 2] >> 4;
|
|
27
|
+
const rateIndex = (bytes[at + 2] >> 2) & 3;
|
|
28
|
+
if (version === 1 || layer !== 1 || bitrate === 0 || bitrate === 15 || rateIndex === 3) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const mpeg1 = version === 3;
|
|
32
|
+
const rate = RATES[version][rateIndex];
|
|
33
|
+
const padding = (bytes[at + 2] >> 1) & 1;
|
|
34
|
+
const kbps = BITRATES[mpeg1 ? 0 : 1][bitrate];
|
|
35
|
+
return {
|
|
36
|
+
version,
|
|
37
|
+
rate,
|
|
38
|
+
channels: bytes[at + 3] >> 6 === 3 ? 1 : 2,
|
|
39
|
+
samples: mpeg1 ? 1152 : 576,
|
|
40
|
+
length: Math.floor(((mpeg1 ? 144 : 72) * kbps * 1000) / rate) + padding,
|
|
41
|
+
mpeg1,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** A header of the stream's kind at `at`: its version, rate and channels those of `like`. */
|
|
45
|
+
function frameAt(bytes, at, like) {
|
|
46
|
+
const h = header(bytes, at);
|
|
47
|
+
if (!h ||
|
|
48
|
+
(like && (h.version !== like.version || h.rate !== like.rate || h.channels !== like.channels))) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return h;
|
|
52
|
+
}
|
|
53
|
+
/** A header at `at` the next frames' headers follow, as many as the bytes hold up to a run. */
|
|
54
|
+
function runAt(bytes, at, like) {
|
|
55
|
+
const first = frameAt(bytes, at, like);
|
|
56
|
+
let next = first ? at + first.length : 0;
|
|
57
|
+
for (let k = 1; first && k < RUN && next + 4 <= bytes.length; k++) {
|
|
58
|
+
const h = frameAt(bytes, next, first);
|
|
59
|
+
if (!h) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
next += h.length;
|
|
63
|
+
}
|
|
64
|
+
return first;
|
|
65
|
+
}
|
|
66
|
+
/** The length of an ID3v2 tag at `at`, header, body and footer, or 0 for none. */
|
|
67
|
+
function id3Length(bytes, at) {
|
|
68
|
+
if (at + 10 > bytes.length ||
|
|
69
|
+
bytes[at] !== 0x49 ||
|
|
70
|
+
bytes[at + 1] !== 0x44 ||
|
|
71
|
+
bytes[at + 2] !== 0x33 ||
|
|
72
|
+
(bytes[at + 6] | bytes[at + 7] | bytes[at + 8] | bytes[at + 9]) & 0x80) {
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
// Its size in seven-bit bytes.
|
|
76
|
+
const size = (bytes[at + 6] << 21) | (bytes[at + 7] << 14) | (bytes[at + 8] << 7) | bytes[at + 9];
|
|
77
|
+
return 10 + size + (bytes[at + 5] & 0x10 ? 10 : 0);
|
|
78
|
+
}
|
|
79
|
+
/** The next run of frames from `at`, past tags and anything else, and where it starts; null for none. */
|
|
80
|
+
function nextRun(bytes, at, like) {
|
|
81
|
+
for (let p = at; p + 4 <= bytes.length;) {
|
|
82
|
+
const tag = id3Length(bytes, p);
|
|
83
|
+
if (tag) {
|
|
84
|
+
p += tag;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const h = runAt(bytes, p, like);
|
|
88
|
+
if (h) {
|
|
89
|
+
return [p, h];
|
|
90
|
+
}
|
|
91
|
+
p++;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The frames of MP3 bytes, or null for bytes with none. Given what it read
|
|
97
|
+
* of the bytes before more came after them, it reads on from there.
|
|
98
|
+
*/
|
|
99
|
+
export function mp3Frames(bytes, before = null) {
|
|
100
|
+
const like = before?.whole.length ? header(bytes, before.whole[0]) : null;
|
|
101
|
+
if (!like) {
|
|
102
|
+
const run = nextRun(bytes, 0, null);
|
|
103
|
+
return run ? readFrames(bytes, run[0], run[1], []) : null;
|
|
104
|
+
}
|
|
105
|
+
return readFrames(bytes, before?.end ?? 0, like, before?.whole ?? []);
|
|
106
|
+
}
|
|
107
|
+
function readFrames(bytes, from, like, before) {
|
|
108
|
+
const whole = before.slice();
|
|
109
|
+
let frames = whole.length / 2;
|
|
110
|
+
let at = from;
|
|
111
|
+
let end = from;
|
|
112
|
+
while (at + 4 <= bytes.length) {
|
|
113
|
+
let h = frameAt(bytes, at, like);
|
|
114
|
+
if (!h) {
|
|
115
|
+
const run = nextRun(bytes, at, like);
|
|
116
|
+
if (!run) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
[at, h] = run;
|
|
120
|
+
}
|
|
121
|
+
frames++;
|
|
122
|
+
if (at + h.length > bytes.length) {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
whole.push(at, at + h.length);
|
|
126
|
+
at += h.length;
|
|
127
|
+
end = at;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
rate: like.rate,
|
|
131
|
+
channels: like.channels,
|
|
132
|
+
samplesPerFrame: like.samples,
|
|
133
|
+
frames,
|
|
134
|
+
whole,
|
|
135
|
+
end,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** Whether the frame at `at` is a Xing, Info or VBRI header rather than sound. */
|
|
139
|
+
function isHeaderFrame(bytes, at, h) {
|
|
140
|
+
const tag = (offset) => String.fromCharCode(...bytes.subarray(at + offset, at + offset + 4));
|
|
141
|
+
const side = h.mpeg1 ? (h.channels === 1 ? 17 : 32) : h.channels === 1 ? 9 : 17;
|
|
142
|
+
const xing = tag(4 + side);
|
|
143
|
+
return xing === "Xing" || xing === "Info" || tag(36) === "VBRI";
|
|
144
|
+
}
|
|
145
|
+
/** The first frame's gapless metadata, without scanning and retaining every frame of a long sound. */
|
|
146
|
+
export function mp3HeaderFrame(bytes) {
|
|
147
|
+
const first = nextRun(bytes, 0, null);
|
|
148
|
+
if (!first || !isHeaderFrame(bytes, first[0], first[1])) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
return [first[0], Math.min(bytes.length, first[0] + first[1].length)];
|
|
152
|
+
}
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import { dispatchEvent } from "../scripting/events.js";
|
|
2
|
+
import { streamSound, } from "./audio.js";
|
|
3
|
+
export const channels = new WeakMap();
|
|
4
|
+
/** SoundMixer's transform, applied over every channel's own. */
|
|
5
|
+
export const mixerMixes = new WeakMap();
|
|
6
|
+
export const mixOf = (o) => ({
|
|
7
|
+
volume: o?.$soundVolume ?? 1,
|
|
8
|
+
leftToLeft: o?.$soundLeftToLeft ?? 1,
|
|
9
|
+
leftToRight: o?.$soundLeftToRight ?? 0,
|
|
10
|
+
rightToLeft: o?.$soundRightToLeft ?? 0,
|
|
11
|
+
rightToRight: o?.$soundRightToRight ?? 1,
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* What a channel sends to the device: its own transform and the mixer's,
|
|
15
|
+
* combined as Ruffle's SoundTransform::concat computes them. Only
|
|
16
|
+
* transforms that both cross channels depend on the order, which no trace
|
|
17
|
+
* can show; Ruffle's is kept.
|
|
18
|
+
*/
|
|
19
|
+
export function outputMix(local, global) {
|
|
20
|
+
return {
|
|
21
|
+
volume: Math.abs(local.volume * global.volume),
|
|
22
|
+
leftToLeft: local.leftToLeft * global.leftToLeft + local.rightToLeft * global.leftToRight,
|
|
23
|
+
leftToRight: local.leftToRight * global.leftToLeft + local.rightToRight * global.leftToRight,
|
|
24
|
+
rightToLeft: local.leftToLeft * global.rightToLeft + local.rightToLeft * global.rightToRight,
|
|
25
|
+
rightToRight: local.leftToRight * global.rightToLeft + local.rightToRight * global.rightToRight,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export const mixerMix = (s) => mixerMixes.get(s) ?? mixOf(null);
|
|
29
|
+
const hosts = new WeakMap();
|
|
30
|
+
/** An AS3 movie's SoundHost: its device, clock and symbols, its sprites' and SoundMixer's transforms. */
|
|
31
|
+
export function soundHostOf(s) {
|
|
32
|
+
let host = hosts.get(s);
|
|
33
|
+
if (!host) {
|
|
34
|
+
host = {
|
|
35
|
+
get audio() {
|
|
36
|
+
return s.audio;
|
|
37
|
+
},
|
|
38
|
+
get now() {
|
|
39
|
+
return s.timers.now;
|
|
40
|
+
},
|
|
41
|
+
get frames() {
|
|
42
|
+
return s.frames;
|
|
43
|
+
},
|
|
44
|
+
get frameRate() {
|
|
45
|
+
return s.frameRate;
|
|
46
|
+
},
|
|
47
|
+
soundClip: (character) => s.symbols.soundClip(character),
|
|
48
|
+
ownMix: (o) => o.object?.$soundMix,
|
|
49
|
+
get mixer() {
|
|
50
|
+
return mixerMix(s);
|
|
51
|
+
},
|
|
52
|
+
scriptSounds() {
|
|
53
|
+
let n = 0;
|
|
54
|
+
for (const channel of channels.get(s) ?? []) {
|
|
55
|
+
const state = channel.$channel;
|
|
56
|
+
if (!state.stopped && (state.dynamic || state.sound.length > 0)) {
|
|
57
|
+
n++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return n;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
hosts.set(s, host);
|
|
64
|
+
}
|
|
65
|
+
return host;
|
|
66
|
+
}
|
|
67
|
+
export const positionOf = (s, state) => state.stopped
|
|
68
|
+
? state.stoppedAt
|
|
69
|
+
: (state.dynamic?.position() ??
|
|
70
|
+
Math.min(state.sound.length, state.start + Math.max(0, s.timers.now - state.started)));
|
|
71
|
+
export function stopChannel(s, state) {
|
|
72
|
+
state.stoppedAt = positionOf(s, state);
|
|
73
|
+
state.stopped = true;
|
|
74
|
+
state.playing?.stop();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* SoundMixer.stopAll: every channel stays where it was, and none completes;
|
|
78
|
+
* the timeline's sounds stop too, though a stream starts again at the next
|
|
79
|
+
* block its clip plays on to, as Ruffle has it.
|
|
80
|
+
*/
|
|
81
|
+
export function stopAllSounds(s) {
|
|
82
|
+
const active = channels.get(s);
|
|
83
|
+
for (const channel of active ?? []) {
|
|
84
|
+
stopChannel(s, channel.$channel);
|
|
85
|
+
}
|
|
86
|
+
active?.clear();
|
|
87
|
+
stopTimelineSounds(soundHostOf(s));
|
|
88
|
+
}
|
|
89
|
+
/** Every sound the timeline, or AVM1's Sound, started stops, none completing. */
|
|
90
|
+
export function stopTimelineSounds(h) {
|
|
91
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
92
|
+
stopTimelineSound(h, sound);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const timelineSounds = new WeakMap();
|
|
96
|
+
const streamSounds = new WeakMap();
|
|
97
|
+
/** How long a sound over by the clock may still sound on the device before it is stopped. */
|
|
98
|
+
const TAIL = 100;
|
|
99
|
+
/**
|
|
100
|
+
* The sounds that may play at once, timeline and script alike: Flash's 32
|
|
101
|
+
* channels, Ruffle's AudioManager::MAX_SOUNDS. A timeline sound past them
|
|
102
|
+
* does not start, nor queue on a device that is not yet running.
|
|
103
|
+
*/
|
|
104
|
+
export const MAX_SOUNDS = 32;
|
|
105
|
+
/** Whether the device has, or will have, a timeline sound playing. */
|
|
106
|
+
function onDevice(sound) {
|
|
107
|
+
if (sound.stream) {
|
|
108
|
+
return sound.decoding || (!!sound.playing && sound.playing.ended !== true);
|
|
109
|
+
}
|
|
110
|
+
return (sound.endedAt === null || sound.decoding || (!!sound.playing && sound.playing.ended !== true));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The sounds that hold a channel: a script's whose sound is there to play
|
|
114
|
+
* (one still loading holds none until it can start), and the timeline's
|
|
115
|
+
* the device has or will have.
|
|
116
|
+
*/
|
|
117
|
+
export function liveSounds(s) {
|
|
118
|
+
return liveSoundsOf(soundHostOf(s));
|
|
119
|
+
}
|
|
120
|
+
function liveSoundsOf(h) {
|
|
121
|
+
let n = h.scriptSounds();
|
|
122
|
+
for (const sound of timelineSounds.get(h) ?? []) {
|
|
123
|
+
if (onDevice(sound)) {
|
|
124
|
+
n++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return n;
|
|
128
|
+
}
|
|
129
|
+
/** SOUNDINFO's points and envelope are in samples at 44.1 kHz, whatever the sound's rate. */
|
|
130
|
+
const ENVELOPE_RATE = 44.1;
|
|
131
|
+
/**
|
|
132
|
+
* What a timeline sound sends to the device: the transforms of its owner
|
|
133
|
+
* and each ancestor, then the mixer's, concatenated as Ruffle's
|
|
134
|
+
* transform_for_sound does. A sprite's is its soundTransform; a button's
|
|
135
|
+
* is the mixer's, so it has none of its own.
|
|
136
|
+
*/
|
|
137
|
+
function timelineMix(h, owner) {
|
|
138
|
+
let mix = mixOf(null);
|
|
139
|
+
for (let o = owner; o; o = o.parent) {
|
|
140
|
+
const own = h.ownMix(o);
|
|
141
|
+
if (own) {
|
|
142
|
+
mix = outputMix(mix, own);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return outputMix(mix, h.mixer);
|
|
146
|
+
}
|
|
147
|
+
/** A sprite's transform or the mixer's changed: every timeline sound's mix follows. */
|
|
148
|
+
export function updateTimelineMixes(s) {
|
|
149
|
+
updateMixes(soundHostOf(s));
|
|
150
|
+
}
|
|
151
|
+
export function updateMixes(h) {
|
|
152
|
+
for (const sound of timelineSounds.get(h) ?? []) {
|
|
153
|
+
sound.playing?.setMix(timelineMix(h, sound.owner));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export function stopTimelineSound(h, sound) {
|
|
157
|
+
sound.stoppedAt ??= h.now;
|
|
158
|
+
sound.stopped = true;
|
|
159
|
+
sound.playing?.stop();
|
|
160
|
+
timelineSounds.get(h)?.delete(sound);
|
|
161
|
+
if (sound.stream) {
|
|
162
|
+
streamSounds.get(h)?.delete(sound);
|
|
163
|
+
}
|
|
164
|
+
if (sound.clip?.stream === sound) {
|
|
165
|
+
sound.clip.stream = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function playTimelineSound(h, owner, character, clip, start, loops, shape, duration) {
|
|
169
|
+
const task = h.soundClip(character);
|
|
170
|
+
if (!task || liveSoundsOf(h) >= MAX_SOUNDS) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const sound = {
|
|
174
|
+
owner,
|
|
175
|
+
character,
|
|
176
|
+
clip,
|
|
177
|
+
started: h.now,
|
|
178
|
+
duration,
|
|
179
|
+
playing: null,
|
|
180
|
+
stopped: false,
|
|
181
|
+
decoding: true,
|
|
182
|
+
endedAt: null,
|
|
183
|
+
onEnd: null,
|
|
184
|
+
stoppedAt: null,
|
|
185
|
+
stream: null,
|
|
186
|
+
};
|
|
187
|
+
let active = timelineSounds.get(h);
|
|
188
|
+
if (!active) {
|
|
189
|
+
active = new Set();
|
|
190
|
+
timelineSounds.set(h, active);
|
|
191
|
+
}
|
|
192
|
+
active.add(sound);
|
|
193
|
+
void task.then((decoded) => {
|
|
194
|
+
sound.decoding = false;
|
|
195
|
+
// A stream whose decode took frames starts as far in as the clock has
|
|
196
|
+
// run, to keep with its timeline; an event sound plays whole, late.
|
|
197
|
+
const late = Math.max(0, h.now - sound.started);
|
|
198
|
+
if (!sound.stopped && (!clip || late < sound.duration)) {
|
|
199
|
+
sound.playing = decoded.play(start, loops, timelineMix(h, owner), clip ? { ...shape, atMs: late } : shape);
|
|
200
|
+
}
|
|
201
|
+
}, () => {
|
|
202
|
+
sound.decoding = false;
|
|
203
|
+
});
|
|
204
|
+
return sound;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* An event sound, as StartSound and a button start one: SyncStop stops
|
|
208
|
+
* every instance of the sound the timeline started, SyncNoMultiple starts
|
|
209
|
+
* none while one plays, and otherwise it plays from its in point to its
|
|
210
|
+
* out point, as many loops as it says, under its envelope. AS3's channels
|
|
211
|
+
* of the sound are left be: adl plays one on through a SyncStop of it.
|
|
212
|
+
*/
|
|
213
|
+
function startEventSound(h, owner, character, info) {
|
|
214
|
+
const active = timelineSounds.get(h);
|
|
215
|
+
if (info.stop) {
|
|
216
|
+
for (const sound of [...(active ?? [])]) {
|
|
217
|
+
if (sound.character === character) {
|
|
218
|
+
stopTimelineSound(h, sound);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (info.noMultiple &&
|
|
224
|
+
active &&
|
|
225
|
+
[...active].some((sound) => sound.character === character && sound.endedAt === null)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const definition = character.definition;
|
|
229
|
+
const length = (definition.sampleCount * 1000) / definition.sampleRate;
|
|
230
|
+
const start = (info.inPoint ?? 0) / ENVELOPE_RATE;
|
|
231
|
+
const end = info.outPoint === null ? length : Math.min(length, info.outPoint / ENVELOPE_RATE);
|
|
232
|
+
const loops = Math.max(1, info.loops);
|
|
233
|
+
const shape = {};
|
|
234
|
+
if (info.outPoint !== null) {
|
|
235
|
+
shape.endMs = end;
|
|
236
|
+
}
|
|
237
|
+
if (info.envelope) {
|
|
238
|
+
shape.envelope = info.envelope.map((point) => ({
|
|
239
|
+
ms: point.sample / ENVELOPE_RATE,
|
|
240
|
+
left: point.left,
|
|
241
|
+
right: point.right,
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
playTimelineSound(h, owner, character, null, start, loops, shape, Math.max(0, end - start) * loops);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* AVM1's Sound.start: an event sound of `character` from `offset` ms, `loops`
|
|
248
|
+
* times, under `owner`'s transforms (none for the global Sound), whose end
|
|
249
|
+
* `onEnd` hears with the frame; null where it cannot play.
|
|
250
|
+
*/
|
|
251
|
+
export function startScriptSound(h, owner, character, offset, loops, onEnd) {
|
|
252
|
+
const definition = character.definition;
|
|
253
|
+
const length = (definition.sampleCount * 1000) / definition.sampleRate;
|
|
254
|
+
const start = Math.min(length, Math.max(0, offset));
|
|
255
|
+
const sound = playTimelineSound(h, owner, character, null, start, loops, {}, (length - start) * loops);
|
|
256
|
+
if (sound) {
|
|
257
|
+
sound.onEnd = onEnd;
|
|
258
|
+
}
|
|
259
|
+
return sound;
|
|
260
|
+
}
|
|
261
|
+
/** The sounds playing under exactly `owner`, as AVM1's Sound.stop() of a clip stops them; null for the global Sound's. */
|
|
262
|
+
export function soundsOf(h, owner) {
|
|
263
|
+
return [...(timelineSounds.get(h) ?? [])].filter((sound) => sound.owner === owner);
|
|
264
|
+
}
|
|
265
|
+
/** Every sound of `character` stops, whoever started it, as AVM1's Sound.stop(name) does. */
|
|
266
|
+
export function stopSoundsOf(h, character) {
|
|
267
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
268
|
+
if (sound.character === character) {
|
|
269
|
+
stopTimelineSound(h, sound);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/** The DefineSound a StartSound names, by id or, for StartSound2, by the class bound to it. */
|
|
274
|
+
function startSoundCharacter(library, start) {
|
|
275
|
+
let id = start.id;
|
|
276
|
+
if (start.className !== null) {
|
|
277
|
+
const dot = start.className.lastIndexOf(".");
|
|
278
|
+
const name = dot < 0
|
|
279
|
+
? start.className
|
|
280
|
+
: `${start.className.slice(0, dot)}::${start.className.slice(dot + 1)}`;
|
|
281
|
+
id = null;
|
|
282
|
+
for (const [bound, className] of library.classes) {
|
|
283
|
+
if (className === name) {
|
|
284
|
+
id = bound;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const character = id === null ? undefined : library.characters.get(id);
|
|
290
|
+
return character?.type === "sound" ? character : null;
|
|
291
|
+
}
|
|
292
|
+
/** A stream's blocks made one sound on its first play, shared by every clip of its timeline. */
|
|
293
|
+
function streamOf(stream) {
|
|
294
|
+
if (!stream.sound) {
|
|
295
|
+
const { sound, starts } = streamSound(stream.head, stream.blocks);
|
|
296
|
+
stream.sound = { character: { type: "sound", id: 0, definition: sound }, starts };
|
|
297
|
+
}
|
|
298
|
+
return stream.sound;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* The block on `frame` of a playing clip with no stream playing starts it
|
|
302
|
+
* from there, as Ruffle's sound_stream_block does, to the end of the run of
|
|
303
|
+
* frames with blocks after it, where Ruffle's stream ends, whatever its
|
|
304
|
+
* format: a gap is silence, as the frames carry no sound there, and the
|
|
305
|
+
* next block starts the stream again from its own samples. An MP3 stream
|
|
306
|
+
* that played on over a gap ran ahead of its timeline by the gap's length,
|
|
307
|
+
* a scene's narration heard before its pictures. Its device cursor lets
|
|
308
|
+
* the player advance overdue frames together, drawing only after the
|
|
309
|
+
* batch.
|
|
310
|
+
*/
|
|
311
|
+
function startStream(h, clip, stream, frame) {
|
|
312
|
+
const block = stream.byFrame.get(frame);
|
|
313
|
+
if (block === undefined || !clip.playing || clip.stream) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// What the timeline took off plays the frame it went in, but its streams no more.
|
|
317
|
+
let top = clip;
|
|
318
|
+
while (top.parent) {
|
|
319
|
+
top = top.parent;
|
|
320
|
+
}
|
|
321
|
+
if (unloaded.get(top) === h.frames) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
// The last moments of its stream before, over by the clock, give way to this one.
|
|
325
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
326
|
+
if (sound.clip === clip) {
|
|
327
|
+
stopTimelineSound(h, sound);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const { character, starts } = streamOf(stream);
|
|
331
|
+
let last = block + 1;
|
|
332
|
+
while (stream.byFrame.get(frame + last - block) === last) {
|
|
333
|
+
last++;
|
|
334
|
+
}
|
|
335
|
+
const rate = character.definition.sampleRate;
|
|
336
|
+
const start = (starts[block] * 1000) / rate;
|
|
337
|
+
const end = (starts[last] * 1000) / rate;
|
|
338
|
+
const sound = playTimelineSound(h, clip, character, clip, start, 1, { endMs: end }, end - start);
|
|
339
|
+
clip.stream = sound;
|
|
340
|
+
if (sound) {
|
|
341
|
+
sound.stream = {
|
|
342
|
+
elapsedMs: 0,
|
|
343
|
+
endFrame: frame + last - block,
|
|
344
|
+
};
|
|
345
|
+
let active = streamSounds.get(h);
|
|
346
|
+
if (!active) {
|
|
347
|
+
active = new Set();
|
|
348
|
+
streamSounds.set(h, active);
|
|
349
|
+
}
|
|
350
|
+
active.add(sound);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/** Whole frames by which a playing stream's device is ahead of its timeline. */
|
|
354
|
+
export function streamFrames(h) {
|
|
355
|
+
const active = streamSounds.get(h);
|
|
356
|
+
if (!active || active.size === 0) {
|
|
357
|
+
return 0;
|
|
358
|
+
}
|
|
359
|
+
let frames = 0;
|
|
360
|
+
const frameMs = 1000 / h.frameRate;
|
|
361
|
+
for (const sound of active) {
|
|
362
|
+
if (sound.stream && sound.clip?.stream === sound) {
|
|
363
|
+
const position = sound.playing?.positionMs;
|
|
364
|
+
if (position !== undefined && Number.isFinite(position)) {
|
|
365
|
+
frames = Math.max(frames, Math.floor((position - sound.stream.elapsedMs) / frameMs + 1e-7));
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return frames;
|
|
370
|
+
}
|
|
371
|
+
/** What the timeline took off, by the frame it did. */
|
|
372
|
+
const unloaded = new WeakMap();
|
|
373
|
+
/** Whether `inner` is `outer` or under it. */
|
|
374
|
+
function within(inner, outer) {
|
|
375
|
+
for (let o = inner; o; o = o.parent) {
|
|
376
|
+
if (o === outer) {
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
/** unloadAndStop: the sounds of the timelines under `display` stop, its event sounds too. */
|
|
383
|
+
export function stopTimelineSoundsUnder(s, display) {
|
|
384
|
+
const h = soundHostOf(s);
|
|
385
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
386
|
+
if (within(sound.owner, display)) {
|
|
387
|
+
stopTimelineSound(h, sound);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/** What plays the timelines' sounds of every library a host loads. */
|
|
392
|
+
export function timelineSoundsOf(h) {
|
|
393
|
+
return {
|
|
394
|
+
frame(clip, frame) {
|
|
395
|
+
if (!h.audio) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const timeline = clip.timeline;
|
|
399
|
+
const sound = clip.stream;
|
|
400
|
+
if (sound?.stream) {
|
|
401
|
+
if (frame >= sound.stream.endFrame) {
|
|
402
|
+
stopTimelineSound(h, sound);
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
sound.stream.elapsedMs += 1000 / h.frameRate;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
for (const start of timeline.sounds.get(frame) ?? []) {
|
|
409
|
+
const character = startSoundCharacter(clip.library, start);
|
|
410
|
+
if (character) {
|
|
411
|
+
startEventSound(h, clip, character, start.info);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (timeline.stream) {
|
|
415
|
+
startStream(h, clip, timeline.stream, frame);
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
stopStream(clip) {
|
|
419
|
+
clip.stream = null;
|
|
420
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
421
|
+
if (sound.clip === clip) {
|
|
422
|
+
stopTimelineSound(h, sound);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
start(owner, library, id, info) {
|
|
427
|
+
const character = library.characters.get(id);
|
|
428
|
+
if (h.audio && character?.type === "sound") {
|
|
429
|
+
startEventSound(h, owner, character, info);
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
removed(display) {
|
|
433
|
+
if (!h.audio) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
unloaded.set(display, h.frames);
|
|
437
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
438
|
+
if (sound.clip && within(sound.clip, display)) {
|
|
439
|
+
stopTimelineSound(h, sound);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* The timeline's sounds that have played their time are over, with the
|
|
447
|
+
* frame: a NoMultiple may start one again, and AVM1 Sound's hears it.
|
|
448
|
+
* Streams remain attached until the timeline passes their blocks: the
|
|
449
|
+
* device finishing first must not restart one from a lagging frame.
|
|
450
|
+
*/
|
|
451
|
+
export function finishTimelineSounds(h) {
|
|
452
|
+
const ended = [];
|
|
453
|
+
for (const sound of [...(timelineSounds.get(h) ?? [])]) {
|
|
454
|
+
if (sound.stream) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (sound.endedAt === null && h.now - sound.started >= sound.duration) {
|
|
458
|
+
sound.endedAt = h.now;
|
|
459
|
+
if (sound.clip?.stream === sound) {
|
|
460
|
+
sound.clip.stream = null;
|
|
461
|
+
}
|
|
462
|
+
if (sound.onEnd) {
|
|
463
|
+
ended.push(sound);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
else if (sound.endedAt !== null && !onDevice(sound)) {
|
|
467
|
+
stopTimelineSound(h, sound);
|
|
468
|
+
}
|
|
469
|
+
else if (sound.endedAt !== null &&
|
|
470
|
+
sound.playing?.ended === undefined &&
|
|
471
|
+
h.now - sound.endedAt >= TAIL) {
|
|
472
|
+
stopTimelineSound(h, sound);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
for (const sound of ended) {
|
|
476
|
+
sound.onEnd?.();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
/** Sound completions run with the next SWF frame, even if the device ended between frames. */
|
|
480
|
+
export function finishSounds(s) {
|
|
481
|
+
finishTimelineSounds(soundHostOf(s));
|
|
482
|
+
const active = channels.get(s);
|
|
483
|
+
if (!active) {
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
for (const channel of [...active]) {
|
|
487
|
+
const state = channel.$channel;
|
|
488
|
+
if (state.stopped) {
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
if (state.dynamic) {
|
|
492
|
+
state.dynamic.pump();
|
|
493
|
+
if (state.stopped || !active.has(channel) || !state.dynamic.complete()) {
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
const duration = (state.sound.length - state.start) * Math.max(1, state.loops);
|
|
499
|
+
if (state.sound.length <= 0 || s.timers.now - state.started < duration) {
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
stopChannel(s, state);
|
|
504
|
+
active.delete(channel);
|
|
505
|
+
dispatchEvent(s, channel, s.event("soundComplete"));
|
|
506
|
+
}
|
|
507
|
+
}
|