mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #21158 - ferjm:webaudio, r=manishearth,nox,ferjm
WebAudio API - [X] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #6710 - [X] There are tests for these changes This PR adds basic support for the WebAudio API using [servo-media](https://github.com/servo/media) with GStreamer as the audio backend. There are still some major stuff to fix like: - [x] Detach ArrayBuffer during the [AudioBuffer "acquire the content" operation](https://webaudio.github.io/web-audio-api/#acquire-the-content). I am naively using `JS_StealArrayBufferContents()` directly, because it is what Gecko uses, but this should probably be part of the [rust-mozjs](https://github.com/servo/rust-mozjs) [TypedArray](https://github.com/servo/rust-mozjs/blob/master/src/typedarray.rs) API. And, in any case, I am not even sure if that's the proper way to do it. According to the results of the WPTs it may not even be right since [this assertion](https://github.com/servo/rust-mozjs/blob/master/src/typedarray.rs#L285) is failing in some cases. I need to dig more about this. - [x] Disable the GStreamer dependency on Android. Unfortunately gstreamer-rs requires an NDK version upgrade, so we need to disable this for Android until then. I tried adding [different features to servo-media](https://github.com/servo/media/pull/79), but I am currently hitting [this issue](https://github.com/rust-lang/cargo/issues/1197) I still need to run servo-tidy, change the servo-media dependency to use the git repo and add/fix some comments and TODOs. The remaining feature work should be done in future PRs. Note that most of the failing WPTs are failing because we don't implement the tested features yet (we only implement a few AudioNodes) and we have no OfflineAudioContext support, which most WPTs rely on. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21158) <!-- Reviewable:end -->
This commit is contained in:
commit
0051597525
199 changed files with 5178 additions and 25 deletions
|
@ -17,6 +17,13 @@ matrix:
|
|||
- sudo add-apt-repository 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.9 main' -y
|
||||
- sudo apt-get update -q
|
||||
- sudo apt-get install clang-3.9 llvm-3.9 llvm-3.9-runtime -y
|
||||
- curl -L https://github.com/ferjm/gstreamer-1.14.1-ubuntu-trusty/raw/master/gstreamer.tar.gz | tar xz
|
||||
- sed -i "s;prefix=/root/gstreamer;prefix=$PWD/gstreamer;g" $PWD/gstreamer/lib/x86_64-linux-gnu/pkgconfig/*.pc
|
||||
- export PKG_CONFIG_PATH=$PWD/gstreamer/lib/x86_64-linux-gnu/pkgconfig
|
||||
- export GST_PLUGIN_SYSTEM_PATH=$PWD/gstreamer/lib/x86_64-linux-gnu/gstreamer-1.0
|
||||
- export GST_PLUGIN_SCANNER=$PWD/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner
|
||||
- export PATH=$PATH:$PWD/gstreamer/bin
|
||||
- export LD_LIBRARY_PATH=$PWD/gstreamer/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
|
||||
- export LLVM_CONFIG=/usr/lib/llvm-3.9/bin/llvm-config
|
||||
- curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -y
|
||||
- source ~/.profile
|
||||
|
@ -52,6 +59,7 @@ matrix:
|
|||
- ccache
|
||||
- libdbus-glib-1-dev
|
||||
- libedit-dev
|
||||
- libglib2.0-dev
|
||||
|
||||
branches:
|
||||
only:
|
||||
|
|
446
Cargo.lock
generated
446
Cargo.lock
generated
|
@ -45,6 +45,14 @@ dependencies = [
|
|||
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "array-init"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.6"
|
||||
|
@ -250,6 +258,16 @@ dependencies = [
|
|||
"alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.1"
|
||||
|
@ -264,6 +282,24 @@ dependencies = [
|
|||
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2-sys"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "canvas"
|
||||
version = "0.0.1"
|
||||
|
@ -525,6 +561,14 @@ dependencies = [
|
|||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.2.0"
|
||||
|
@ -821,7 +865,7 @@ version = "0.3.0"
|
|||
source = "git+https://github.com/energymon/energymon-sys.git#f8d77ea2906b25f9c0fd358aa9d300a46dc3e97c"
|
||||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -895,7 +939,7 @@ version = "2.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -906,6 +950,11 @@ dependencies = [
|
|||
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.1"
|
||||
|
@ -913,6 +962,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1088,6 +1138,28 @@ dependencies = [
|
|||
"gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.2.11"
|
||||
|
@ -1124,6 +1196,191 @@ dependencies = [
|
|||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"muldiv 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-app"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-app-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-app-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-audio"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-audio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-audio-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-base"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-base-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-player"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-player-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-video 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-player-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-video-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-video"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-video-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-video-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gvr-sys"
|
||||
version = "0.7.0"
|
||||
|
@ -1141,7 +1398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1168,7 +1425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1269,7 +1526,7 @@ dependencies = [
|
|||
"lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1533,7 +1790,7 @@ name = "libdbus-sys"
|
|||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1594,7 +1851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1785,6 +2042,26 @@ dependencies = [
|
|||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide_c_api"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.12"
|
||||
|
@ -1867,6 +2144,15 @@ dependencies = [
|
|||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "msdos_time"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "msg"
|
||||
version = "0.0.1"
|
||||
|
@ -1879,6 +2165,11 @@ dependencies = [
|
|||
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "muldiv"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "net"
|
||||
version = "0.0.1"
|
||||
|
@ -2026,11 +2317,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.1.36"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2136,10 +2427,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "osmesa-src"
|
||||
version = "18.1.0-devel"
|
||||
|
@ -2204,6 +2500,15 @@ name = "percent-encoding"
|
|||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.7.21"
|
||||
|
@ -2241,7 +2546,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.9"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -2266,6 +2571,11 @@ dependencies = [
|
|||
"num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "podio"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
|
@ -2597,6 +2907,7 @@ dependencies = [
|
|||
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-media 0.1.0 (git+https://github.com/servo/media)",
|
||||
"servo_allocator 0.0.1",
|
||||
"servo_arc 0.1.1",
|
||||
"servo_atoms 0.0.1",
|
||||
|
@ -2809,7 +3120,7 @@ version = "4.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -2819,9 +3130,54 @@ version = "4.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo-media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/media#06774e4a05aee58d62d3facc8388c3ff175edec0"
|
||||
dependencies = [
|
||||
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
|
||||
"servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)",
|
||||
"servo-media-player 0.1.0 (git+https://github.com/servo/media)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo-media-audio"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/media#06774e4a05aee58d62d3facc8388c3ff175edec0"
|
||||
dependencies = [
|
||||
"byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_media_derive 0.1.0 (git+https://github.com/servo/media)",
|
||||
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo-media-gstreamer"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/media#06774e4a05aee58d62d3facc8388c3ff175edec0"
|
||||
dependencies = [
|
||||
"byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-app 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-audio 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-player 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
|
||||
"servo-media-player 0.1.0 (git+https://github.com/servo/media)",
|
||||
"zip 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo-media-player"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/media#06774e4a05aee58d62d3facc8388c3ff175edec0"
|
||||
|
||||
[[package]]
|
||||
name = "servo-skia"
|
||||
version = "0.30000017.0"
|
||||
|
@ -2914,6 +3270,15 @@ dependencies = [
|
|||
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo_media_derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/media#06774e4a05aee58d62d3facc8388c3ff175edec0"
|
||||
dependencies = [
|
||||
"quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo_rand"
|
||||
version = "0.0.1"
|
||||
|
@ -3734,7 +4099,7 @@ version = "2.17.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3753,7 +4118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3789,6 +4154,18 @@ dependencies = [
|
|||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
|
||||
"checksum aho-corasick 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0ba20154ea1f47ce2793322f049c5646cc6d0fa9759d5f333f286e507bf8080"
|
||||
|
@ -3798,6 +4175,7 @@ dependencies = [
|
|||
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
|
||||
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
|
||||
"checksum app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4720c83543de184d9f6add2fdb8e8031543497b8506620884c16e125b493c09"
|
||||
"checksum array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3cc8456d0ae81a8c76f59e384683a601548c38949a4bfcb65dd31ded5c75ff3"
|
||||
"checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
|
||||
"checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
|
||||
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
|
||||
|
@ -3819,8 +4197,12 @@ dependencies = [
|
|||
"checksum blurz 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e73bda0f4c71c63a047351070097f3f507e6718e86b9ee525173371ef7b94b73"
|
||||
"checksum brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fe87b40996b84fdc56e57c165d93079f4b50cb806598118e692ddfaa3d3c57c0"
|
||||
"checksum brotli-decompressor 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "313f4b6cc0b365d6b88eda5aa40175ee34ac6efa9a79e0b3b8202eca90247ba8"
|
||||
"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||
"checksum byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a865e7bfa6c3b79216ccba767d4dc66e4f9f65f1ed4639e73faff3c4a2485d7"
|
||||
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
|
||||
"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9"
|
||||
"checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
|
||||
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
|
||||
"checksum caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "808dab3318747be122cb31d36de18d4d1c81277a76f8332a02b81a3d73463d7f"
|
||||
"checksum cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9be26b24e988625409b19736d130f0c7d224f01d06454b5f81d8d23d6c1a618f"
|
||||
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
|
||||
|
@ -3839,6 +4221,7 @@ dependencies = [
|
|||
"checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
|
||||
"checksum core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e54c4ab33705fa1fc8af375bb7929d68e1c1546c1ecef408966d8c3e49a1d84a"
|
||||
"checksum core-text 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f59bff773954e5cd058a3f5983406b52bec7cc65202bef340ba64a0c40ac91"
|
||||
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
|
@ -3870,6 +4253,7 @@ dependencies = [
|
|||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum euclid 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59b34ec7d95d70d5cda27301d6182bc17abce8b5b52e260f5ff32c677923bbb0"
|
||||
"checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1"
|
||||
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
|
||||
"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
|
||||
"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
|
||||
"checksum fontsan 0.4.0 (git+https://github.com/servo/fontsan)" = "<none>"
|
||||
|
@ -3886,9 +4270,24 @@ dependencies = [
|
|||
"checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c"
|
||||
"checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a"
|
||||
"checksum gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d41e7ac812597988fdae31c9baec3c6d35cadb8ad9ab88a9bf9c0f119ed66c2"
|
||||
"checksum glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e0be1b1432e227bcd1a9b28db9dc1474a7e7fd4227e08e16f35304f32d09b61"
|
||||
"checksum glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615bef979b5838526aee99241afc80cfb2e34a8735d4bcb8ec6072598c18a408"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum glutin 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70c5fe78efbd5a3b243a804ea1032053c584510f8822819f94cfb29b2100317"
|
||||
"checksum glx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "63a6e7c2846e12626455f45ebaff9d92161436dd0fa703d9d198012e528ca7b9"
|
||||
"checksum gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70409d6405db8b1591602fcd0cbe8af52cd9976dd39194442b4c149ba343f86d"
|
||||
"checksum gstreamer 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fcbc083ea31ca8aee35b78ca5eb00af9a59bd765508d8fa836cfb1a4fbb4dd"
|
||||
"checksum gstreamer-app 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e68d96a6a86fe4e4796d7ecb5a3cacd6b4680277da6daea7934612fa8c5c2bf"
|
||||
"checksum gstreamer-app-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a224d33c7780957c30f9280b1256b3882792dda6916f75b54bb30b5b71ed505a"
|
||||
"checksum gstreamer-audio 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "73a7b9c097e8d6fc1967137b574e2d4c646220bcfdd00ba681822e297cb06cb8"
|
||||
"checksum gstreamer-audio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd60631f2dd055f0aae2831e86bd6c1d45e24528d4c478002cc07490dd84b56e"
|
||||
"checksum gstreamer-base 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05ec7a84b4160b61c72ea27ccf3f46eb9c8f996c5991746623e69e3e532e3cb5"
|
||||
"checksum gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "501a7add44f256aab6cb5b65ef121c449197cf55087d6a7586846c8d1e42e88b"
|
||||
"checksum gstreamer-player 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "63e81d78e9e7ee5d448ba50c52722005bbbf1bfe606767c4c407f45e8996f050"
|
||||
"checksum gstreamer-player-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b9476078cc76164446e88b2c4331e81e24a07f7b7c3a8b4bf8975a47998ebd4"
|
||||
"checksum gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2f51e25a6f97dd4bfd640cba96f192f8759b8766afd66d6d9ea0f82ca14a37"
|
||||
"checksum gstreamer-video 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75300cf1ed8d8d65811349fc755fac22be05ea55df551ab29e43664d4a575c92"
|
||||
"checksum gstreamer-video-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed798787e78a0f1c8be06bd3adcab03f962f049a820743aae9f690f56a0d538"
|
||||
"checksum gvr-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1334b94d8ce67319ddc44663daef53d8c1538629a11562530c981dbd9085b9a"
|
||||
"checksum half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d68db75012a85555434ee079e7e6337931f87a087ab2988becbadf64673a7f"
|
||||
"checksum harfbuzz-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bad27f59fc853bb88eca58088d469cd365ff0ccf362d24c4b1c0cbb1b21b3489"
|
||||
|
@ -3939,6 +4338,8 @@ dependencies = [
|
|||
"checksum mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d69889cdc6336ed56b174514ce876c4c3dc564cc23dd872e7bca589bb2a36c8"
|
||||
"checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65"
|
||||
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
|
||||
"checksum miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba430291c9d6cedae28bcd2d49d1c32fc57d60cd49086646c5dd5673a870eb5"
|
||||
"checksum miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5a5b8234d6103ebfba71e29786da4608540f862de5ce980a1c94f86a40ca0d51"
|
||||
"checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
|
||||
|
@ -3947,6 +4348,8 @@ dependencies = [
|
|||
"checksum mozjs_sys 0.51.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74fd4388f18e64881a63ff773edd77dec47adf63bfd6a3055e5f106e1f7c9eaf"
|
||||
"checksum mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ab5f1d2693586420208d1200ce5a51cd44726f055b635176188137aff42c7de"
|
||||
"checksum mp4parse 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f821e3799bc0fd16d9b861fb02fa7ee1b5fba29f45ad591dade105c48ca9a1a0"
|
||||
"checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
|
||||
"checksum muldiv 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cbef5aa2e8cd82a18cc20e26434cc9843e1ef46e55bfabe5bddb022236c5b3e"
|
||||
"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67"
|
||||
"checksum new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ccbebba6fb53a6d2bdcfaf79cb339bc136dee3bfff54dc337a334bafe36476a"
|
||||
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
|
||||
|
@ -3956,7 +4359,7 @@ dependencies = [
|
|||
"checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7"
|
||||
"checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45"
|
||||
"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
|
||||
"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
|
||||
"checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e"
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
|
||||
"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
|
||||
|
@ -3968,6 +4371,7 @@ dependencies = [
|
|||
"checksum ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc665717454399cba557c55ad226148996e9266ee291f8a37a98bb2cded0a490"
|
||||
"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985"
|
||||
"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9"
|
||||
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
||||
"checksum osmesa-src 18.1.0-devel (git+https://github.com/servo/osmesa-src)" = "<none>"
|
||||
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
||||
"checksum ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69b517feac6fc640f0679625defa0998bbcb32871a6901e63063c2abf9c4cbe"
|
||||
|
@ -3977,13 +4381,15 @@ dependencies = [
|
|||
"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
|
||||
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
|
||||
"checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4"
|
||||
"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
|
||||
"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
|
||||
"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
|
||||
"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
|
||||
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
||||
"checksum pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6a52e4dbc8354505ee07e484ab07127e06d87ca6fa7f0a516a2b294e5ad5ad16"
|
||||
"checksum plane-split 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e14382aabad89085fbf714f75d527492bb672725facb9b2ced2fada47cf418c"
|
||||
"checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b"
|
||||
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
|
||||
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
|
||||
"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
|
||||
|
@ -4021,8 +4427,13 @@ dependencies = [
|
|||
"checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
|
||||
"checksum servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "38b494f03009ee81914b0e7d387ad7c145cafcd69747c2ec89b0e17bb94f303a"
|
||||
"checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b"
|
||||
"checksum servo-media 0.1.0 (git+https://github.com/servo/media)" = "<none>"
|
||||
"checksum servo-media-audio 0.1.0 (git+https://github.com/servo/media)" = "<none>"
|
||||
"checksum servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)" = "<none>"
|
||||
"checksum servo-media-player 0.1.0 (git+https://github.com/servo/media)" = "<none>"
|
||||
"checksum servo-skia 0.30000017.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe33a2592a74f2096daf70bcbee39f2d183efcdc81f536a28af3a357baa6f5b0"
|
||||
"checksum servo-websocket 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bac1e2295e72f0525147d993c626761811acf0441dac1cee8707f12dc7f3363"
|
||||
"checksum servo_media_derive 0.1.0 (git+https://github.com/servo/media)" = "<none>"
|
||||
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
|
||||
"checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1"
|
||||
"checksum sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6649e43c1a1e68d29ed56d0dc3b5b6cf3b901da77cf107c4066b9e3da036df5"
|
||||
|
@ -4102,3 +4513,4 @@ dependencies = [
|
|||
"checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1"
|
||||
"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2"
|
||||
"checksum xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead952cf8bab253fb5cb56e1fff780747bbf7a7258fb0451afe645a166050b1f"
|
||||
"checksum zip 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "77ce0ceee93c995954a31f77903925a6a8bb094709445238e344f2107910e29e"
|
||||
|
|
|
@ -83,7 +83,8 @@ sudo apt install git curl autoconf libx11-dev \
|
|||
gperf g++ build-essential cmake virtualenv python-pip \
|
||||
libssl1.0-dev libbz2-dev libosmesa6-dev libxmu6 libxmu-dev \
|
||||
libglu1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev \
|
||||
libharfbuzz-dev ccache clang
|
||||
libharfbuzz-dev ccache clang \
|
||||
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||
```
|
||||
|
||||
If you using a version prior to **Ubuntu 17.04** or **Debian Sid**, replace `libssl1.0-dev` with `libssl-dev`.
|
||||
|
|
|
@ -43,9 +43,17 @@ cache:
|
|||
- .ccache
|
||||
|
||||
install:
|
||||
- choco install pkgconfiglite
|
||||
- appveyor-retry appveyor DownloadFile https://gstreamer.freedesktop.org/data/pkg/windows/1.14.1/gstreamer-1.0-devel-x86_64-1.14.1.msi
|
||||
- appveyor-retry appveyor DownloadFile https://gstreamer.freedesktop.org/data/pkg/windows/1.14.1/gstreamer-1.0-x86_64-1.14.1.msi
|
||||
- msiexec /i gstreamer-1.0-devel-x86_64-1.14.1.msi /quiet /qn /norestart /log install-devel.log
|
||||
- msiexec /i gstreamer-1.0-x86_64-1.14.1.msi /quiet /qn /norestart /log install.log
|
||||
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain none
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- set PKG_CONFIG_PATH=%PKG_CONFIG_PATH%;C:\gstreamer\1.0\x86_64\lib\pkgconfig
|
||||
- set LIB=C:\gstreamer\1.0\x86_64\lib
|
||||
- set LIBPATH=C:\gstreamer\1.0\x86_64\lib
|
||||
- rustup -V
|
||||
- mach rustc --version
|
||||
- mach cargo --version
|
||||
|
|
|
@ -12,6 +12,7 @@ checkbox
|
|||
click
|
||||
close
|
||||
color
|
||||
complete
|
||||
controllerchange
|
||||
cursive
|
||||
date
|
||||
|
@ -19,6 +20,7 @@ datetime-local
|
|||
dir
|
||||
email
|
||||
emptied
|
||||
ended
|
||||
error
|
||||
fantasy
|
||||
fetch
|
||||
|
|
|
@ -10,7 +10,7 @@ name = "fallible"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
smallvec = "0.6"
|
||||
smallvec = "0.6.2"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
|
||||
# This crate effectively does nothing except if the `known_system_malloc`
|
||||
|
|
|
@ -36,7 +36,7 @@ serde = "1.0"
|
|||
servo_arc = {path = "../servo_arc"}
|
||||
servo_atoms = {path = "../atoms"}
|
||||
servo_url = {path = "../url"}
|
||||
smallvec = "0.6"
|
||||
smallvec = "0.6.2"
|
||||
style = {path = "../style"}
|
||||
time = "0.1.12"
|
||||
unicode-bidi = {version = "0.3", features = ["with_serde"]}
|
||||
|
|
|
@ -42,7 +42,7 @@ servo_geometry = {path = "../geometry"}
|
|||
serde_json = "1.0"
|
||||
servo_config = {path = "../config"}
|
||||
servo_url = {path = "../url"}
|
||||
smallvec = "0.6"
|
||||
smallvec = "0.6.2"
|
||||
style = {path = "../style", features = ["servo"]}
|
||||
style_traits = {path = "../style_traits"}
|
||||
unicode-bidi = {version = "0.3", features = ["with_serde"]}
|
||||
|
|
|
@ -87,9 +87,10 @@ servo_arc = {path = "../servo_arc"}
|
|||
servo_atoms = {path = "../atoms"}
|
||||
servo_config = {path = "../config"}
|
||||
servo_geometry = {path = "../geometry" }
|
||||
servo-media = {git = "https://github.com/servo/media"}
|
||||
servo_rand = {path = "../rand"}
|
||||
servo_url = {path = "../url"}
|
||||
smallvec = "0.6"
|
||||
smallvec = "0.6.2"
|
||||
style = {path = "../style", features = ["servo"]}
|
||||
style_traits = {path = "../style_traits"}
|
||||
swapper = "0.1"
|
||||
|
|
310
components/script/dom/audiobuffer.rs
Normal file
310
components/script/dom/audiobuffer.rs
Normal file
|
@ -0,0 +1,310 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audionode::MAX_CHANNEL_COUNT;
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::AudioBufferBinding::{self, AudioBufferMethods, AudioBufferOptions};
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{DetachDataDisposition, Heap, JSAutoCompartment, JSContext, JSObject};
|
||||
use js::jsapi::JS_GetArrayBufferViewBuffer;
|
||||
use js::rust::CustomAutoRooterGuard;
|
||||
use js::rust::wrappers::JS_DetachArrayBuffer;
|
||||
use js::typedarray::{CreateWith, Float32Array};
|
||||
use servo_media::audio::buffer_source_node::AudioBuffer as ServoMediaAudioBuffer;
|
||||
use std::cmp::min;
|
||||
use std::ptr::{self, NonNull};
|
||||
|
||||
// This range is defined by the spec.
|
||||
// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer
|
||||
pub const MIN_SAMPLE_RATE: f32 = 8000.;
|
||||
pub const MAX_SAMPLE_RATE: f32 = 96000.;
|
||||
|
||||
type JSAudioChannel = Heap<*mut JSObject>;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioBuffer {
|
||||
reflector_: Reflector,
|
||||
js_channels: DomRefCell<Vec<JSAudioChannel>>,
|
||||
#[ignore_malloc_size_of = "servo_media"]
|
||||
shared_channels: DomRefCell<ServoMediaAudioBuffer>,
|
||||
sample_rate: f32,
|
||||
length: u32,
|
||||
duration: f64,
|
||||
number_of_channels: u32,
|
||||
}
|
||||
|
||||
impl AudioBuffer {
|
||||
#[allow(unrooted_must_root)]
|
||||
#[allow(unsafe_code)]
|
||||
pub fn new_inherited(number_of_channels: u32, length: u32, sample_rate: f32) -> AudioBuffer {
|
||||
let vec = (0..number_of_channels).map(|_| Heap::default()).collect();
|
||||
AudioBuffer {
|
||||
reflector_: Reflector::new(),
|
||||
js_channels: DomRefCell::new(vec),
|
||||
shared_channels: DomRefCell::new(ServoMediaAudioBuffer::new(
|
||||
number_of_channels as u8,
|
||||
length as usize,
|
||||
)),
|
||||
sample_rate,
|
||||
length,
|
||||
duration: length as f64 / sample_rate as f64,
|
||||
number_of_channels,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
global: &Window,
|
||||
number_of_channels: u32,
|
||||
length: u32,
|
||||
sample_rate: f32,
|
||||
initial_data: Option<&[f32]>,
|
||||
) -> DomRoot<AudioBuffer> {
|
||||
let buffer = AudioBuffer::new_inherited(number_of_channels, length, sample_rate);
|
||||
let buffer = reflect_dom_object(Box::new(buffer), global, AudioBufferBinding::Wrap);
|
||||
buffer.set_channels(initial_data);
|
||||
buffer
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-audiobuffer
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
options: &AudioBufferOptions,
|
||||
) -> Fallible<DomRoot<AudioBuffer>> {
|
||||
if options.numberOfChannels > MAX_CHANNEL_COUNT ||
|
||||
*options.sampleRate < MIN_SAMPLE_RATE ||
|
||||
*options.sampleRate > MAX_SAMPLE_RATE
|
||||
{
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
Ok(AudioBuffer::new(
|
||||
window,
|
||||
options.numberOfChannels,
|
||||
options.length,
|
||||
*options.sampleRate,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn set_channels(&self, initial_data: Option<&[f32]>) {
|
||||
let global = self.global();
|
||||
let cx = global.get_cx();
|
||||
let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get());
|
||||
let chans = self.js_channels.borrow_mut();
|
||||
for channel in 0..self.number_of_channels {
|
||||
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
|
||||
let offset = (channel * self.length) as usize;
|
||||
match initial_data {
|
||||
Some(data) => {
|
||||
let _ = unsafe {
|
||||
Float32Array::create(
|
||||
cx,
|
||||
CreateWith::Slice(&data[offset..offset + (self.length as usize) - 1]),
|
||||
array.handle_mut(),
|
||||
)
|
||||
};
|
||||
},
|
||||
None => {
|
||||
let _ = unsafe {
|
||||
Float32Array::create(
|
||||
cx,
|
||||
CreateWith::Slice(&vec![0.; self.length as usize]),
|
||||
array.handle_mut(),
|
||||
)
|
||||
};
|
||||
},
|
||||
}
|
||||
chans[channel as usize].set(array.get());
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn restore_js_channel_data(&self, cx: *mut JSContext) -> bool {
|
||||
for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
|
||||
if !channel.get().is_null() {
|
||||
// Already have data in JS array.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Move the channel data from shared_channels to js_channels.
|
||||
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
|
||||
let shared_channel = (*self.shared_channels.borrow_mut()).buffers.remove(i);
|
||||
if Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut())
|
||||
.is_err()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
channel.set(array.get());
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#acquire-the-content
|
||||
#[allow(unsafe_code)]
|
||||
pub fn acquire_contents(&self) -> Option<ServoMediaAudioBuffer> {
|
||||
let cx = self.global().get_cx();
|
||||
for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
|
||||
// Step 1.
|
||||
if channel.get().is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
let channel_data = unsafe {
|
||||
typedarray!(in(cx) let array: Float32Array = channel.get());
|
||||
if let Ok(array) = array {
|
||||
let data = array.to_vec();
|
||||
let mut is_shared = false;
|
||||
rooted!(in (cx) let view_buffer =
|
||||
JS_GetArrayBufferViewBuffer(cx, channel.handle(), &mut is_shared));
|
||||
// This buffer is always created unshared
|
||||
debug_assert!(!is_shared);
|
||||
let _ = JS_DetachArrayBuffer(cx, view_buffer.handle(), DetachDataDisposition::KeepData);
|
||||
data
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
channel.set(ptr::null_mut());
|
||||
|
||||
// Step 3.
|
||||
(*self.shared_channels.borrow_mut()).buffers[i] = channel_data;
|
||||
|
||||
// Step 4 will complete turning shared_channels
|
||||
// data into js_channels ArrayBuffers in restore_js_channel_data.
|
||||
}
|
||||
|
||||
self.js_channels.borrow_mut().clear();
|
||||
|
||||
Some((*self.shared_channels.borrow()).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioBufferMethods for AudioBuffer {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-samplerate
|
||||
fn SampleRate(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.sample_rate)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-length
|
||||
fn Length(&self) -> u32 {
|
||||
self.length
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-duration
|
||||
fn Duration(&self) -> Finite<f64> {
|
||||
Finite::wrap(self.duration)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-numberofchannels
|
||||
fn NumberOfChannels(&self) -> u32 {
|
||||
self.number_of_channels
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn GetChannelData(
|
||||
&self,
|
||||
cx: *mut JSContext,
|
||||
channel: u32,
|
||||
) -> Fallible<NonNull<JSObject>> {
|
||||
if channel >= self.number_of_channels {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
if !self.restore_js_channel_data(cx) {
|
||||
return Err(Error::JSFailed);
|
||||
}
|
||||
|
||||
Ok(NonNull::new_unchecked(
|
||||
self.js_channels.borrow()[channel as usize].get(),
|
||||
))
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copyfromchannel
|
||||
#[allow(unsafe_code)]
|
||||
fn CopyFromChannel(
|
||||
&self,
|
||||
mut destination: CustomAutoRooterGuard<Float32Array>,
|
||||
channel_number: u32,
|
||||
start_in_channel: u32,
|
||||
) -> Fallible<()> {
|
||||
if channel_number >= self.number_of_channels || start_in_channel > self.length {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let bytes_to_copy = min(self.length - start_in_channel, destination.len() as u32) as usize;
|
||||
let cx = self.global().get_cx();
|
||||
let channel_number = channel_number as usize;
|
||||
let offset = start_in_channel as usize;
|
||||
let mut dest = Vec::with_capacity(destination.len());
|
||||
|
||||
// We either copy form js_channels or shared_channels.
|
||||
|
||||
let js_channel = self.js_channels.borrow()[channel_number].get();
|
||||
if !js_channel.is_null() {
|
||||
typedarray!(in(cx) let array: Float32Array = js_channel);
|
||||
if let Ok(array) = array {
|
||||
let data = unsafe { array.as_slice() };
|
||||
dest.extend_from_slice(&data[offset..offset + bytes_to_copy]);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(shared_channel) = self.shared_channels.borrow().buffers.get(channel_number) {
|
||||
dest.extend_from_slice(&shared_channel.as_slice()[offset..offset + bytes_to_copy]);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
destination.update(&dest);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copytochannel
|
||||
#[allow(unsafe_code)]
|
||||
fn CopyToChannel(
|
||||
&self,
|
||||
source: CustomAutoRooterGuard<Float32Array>,
|
||||
channel_number: u32,
|
||||
start_in_channel: u32,
|
||||
) -> Fallible<()> {
|
||||
if channel_number >= self.number_of_channels || start_in_channel > (source.len() as u32) {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let cx = self.global().get_cx();
|
||||
if unsafe { !self.restore_js_channel_data(cx) } {
|
||||
return Err(Error::JSFailed);
|
||||
}
|
||||
|
||||
let js_channel = self.js_channels.borrow()[channel_number as usize].get();
|
||||
if js_channel.is_null() {
|
||||
// The array buffer was detached.
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
typedarray!(in(cx) let array: Float32Array = js_channel);
|
||||
if let Ok(mut array) = array {
|
||||
let bytes_to_copy = min(self.length - start_in_channel, source.len() as u32) as usize;
|
||||
let offset = start_in_channel as usize;
|
||||
unsafe {
|
||||
array.update(&source.as_slice()[offset..offset + bytes_to_copy]);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
228
components/script/dom/audiobuffersourcenode.rs
Normal file
228
components/script/dom/audiobuffersourcenode.rs
Normal file
|
@ -0,0 +1,228 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audiobuffer::AudioBuffer;
|
||||
use dom::audioparam::AudioParam;
|
||||
use dom::audioscheduledsourcenode::AudioScheduledSourceNode;
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioBufferSourceNodeBinding;
|
||||
use dom::bindings::codegen::Bindings::AudioBufferSourceNodeBinding::AudioBufferSourceNodeMethods;
|
||||
use dom::bindings::codegen::Bindings::AudioBufferSourceNodeBinding::AudioBufferSourceOptions;
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||
use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
|
||||
use dom::bindings::codegen::Bindings::AudioScheduledSourceNodeBinding::AudioScheduledSourceNodeMethods;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::buffer_source_node::AudioBufferSourceNodeMessage;
|
||||
use servo_media::audio::buffer_source_node::AudioBufferSourceNodeOptions;
|
||||
use servo_media::audio::node::{AudioNodeMessage, AudioNodeInit};
|
||||
use servo_media::audio::param::ParamType;
|
||||
use std::cell::Cell;
|
||||
use std::f32;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioBufferSourceNode {
|
||||
source_node: AudioScheduledSourceNode,
|
||||
buffer: MutNullableDom<AudioBuffer>,
|
||||
playback_rate: Dom<AudioParam>,
|
||||
detune: Dom<AudioParam>,
|
||||
loop_enabled: Cell<bool>,
|
||||
loop_start: Cell<f64>,
|
||||
loop_end: Cell<f64>,
|
||||
}
|
||||
|
||||
impl AudioBufferSourceNode {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn new_inherited(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioBufferSourceOptions,
|
||||
) -> AudioBufferSourceNode {
|
||||
let mut node_options = AudioNodeOptions::empty();
|
||||
node_options.channelCount = Some(2);
|
||||
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
||||
node_options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
||||
let source_node = AudioScheduledSourceNode::new_inherited(
|
||||
AudioNodeInit::AudioBufferSourceNode(options.into()),
|
||||
context,
|
||||
&node_options,
|
||||
0, /* inputs */
|
||||
1, /* outputs */
|
||||
);
|
||||
let node_id = source_node.node().node_id();
|
||||
let playback_rate = AudioParam::new(
|
||||
&window,
|
||||
context,
|
||||
node_id,
|
||||
ParamType::PlaybackRate,
|
||||
AutomationRate::K_rate,
|
||||
*options.playbackRate,
|
||||
f32::MIN,
|
||||
f32::MAX,
|
||||
);
|
||||
let detune = AudioParam::new(
|
||||
&window,
|
||||
context,
|
||||
node_id,
|
||||
ParamType::Detune,
|
||||
AutomationRate::K_rate,
|
||||
*options.detune,
|
||||
f32::MIN,
|
||||
f32::MAX,
|
||||
);
|
||||
AudioBufferSourceNode {
|
||||
source_node,
|
||||
buffer: Default::default(),
|
||||
playback_rate: Dom::from_ref(&playback_rate),
|
||||
detune: Dom::from_ref(&detune),
|
||||
loop_enabled: Cell::new(options.loop_),
|
||||
loop_start: Cell::new(*options.loopStart),
|
||||
loop_end: Cell::new(*options.loopEnd),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioBufferSourceOptions,
|
||||
) -> DomRoot<AudioBufferSourceNode> {
|
||||
let node = AudioBufferSourceNode::new_inherited(window, context, options);
|
||||
reflect_dom_object(Box::new(node), window, AudioBufferSourceNodeBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioBufferSourceOptions,
|
||||
) -> Fallible<DomRoot<AudioBufferSourceNode>> {
|
||||
Ok(AudioBufferSourceNode::new(window, context, options))
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioBufferSourceNodeMethods for AudioBufferSourceNode {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-buffer
|
||||
fn GetBuffer(&self) -> Fallible<Option<DomRoot<AudioBuffer>>> {
|
||||
Ok(self.buffer.get())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-buffer
|
||||
fn SetBuffer(&self, new_buffer: Option<&AudioBuffer>) -> Fallible<()> {
|
||||
if new_buffer.is_some() && self.buffer.get().is_some() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
self.buffer.set(new_buffer);
|
||||
|
||||
if self.source_node.started() {
|
||||
if let Some(buffer) = self.buffer.get() {
|
||||
let buffer = buffer.acquire_contents();
|
||||
self.source_node
|
||||
.node()
|
||||
.message(AudioNodeMessage::AudioBufferSourceNode(
|
||||
AudioBufferSourceNodeMessage::SetBuffer(buffer),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-playbackrate
|
||||
fn PlaybackRate(&self) -> DomRoot<AudioParam> {
|
||||
DomRoot::from_ref(&self.playback_rate)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-detune
|
||||
fn Detune(&self) -> DomRoot<AudioParam> {
|
||||
DomRoot::from_ref(&self.detune)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-loop
|
||||
fn Loop(&self) -> bool {
|
||||
self.loop_enabled.get()
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-loop
|
||||
fn SetLoop(&self, should_loop: bool) {
|
||||
self.loop_enabled.set(should_loop);
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-loopstart
|
||||
fn LoopStart(&self) -> Finite<f64> {
|
||||
Finite::wrap(self.loop_start.get())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-loopstart
|
||||
fn SetLoopStart(&self, loop_start: Finite<f64>) {
|
||||
self.loop_start.set(*loop_start);
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-loopend
|
||||
fn LoopEnd(&self) -> Finite<f64> {
|
||||
Finite::wrap(self.loop_end.get())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-loopend
|
||||
fn SetLoopEnd(&self, loop_end: Finite<f64>) {
|
||||
self.loop_end.set(*loop_end)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-start
|
||||
fn Start(
|
||||
&self,
|
||||
when: Finite<f64>,
|
||||
offset: Option<Finite<f64>>,
|
||||
duration: Option<Finite<f64>>,
|
||||
) -> Fallible<()> {
|
||||
if *when < 0. {
|
||||
return Err(Error::Range("'when' must be a positive value".to_owned()));
|
||||
}
|
||||
|
||||
if let Some(offset) = offset {
|
||||
if *offset < 0. {
|
||||
return Err(Error::Range("'offset' must be a positive value".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(duration) = duration {
|
||||
if *duration < 0. {
|
||||
return Err(Error::Range(
|
||||
"'duration' must be a positive value".to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(buffer) = self.buffer.get() {
|
||||
let buffer = buffer.acquire_contents();
|
||||
self.source_node
|
||||
.node()
|
||||
.message(AudioNodeMessage::AudioBufferSourceNode(
|
||||
AudioBufferSourceNodeMessage::SetBuffer(buffer),
|
||||
));
|
||||
}
|
||||
self.source_node
|
||||
.upcast::<AudioScheduledSourceNode>()
|
||||
.Start(when)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a AudioBufferSourceOptions> for AudioBufferSourceNodeOptions {
|
||||
fn from(options: &'a AudioBufferSourceOptions) -> Self {
|
||||
Self {
|
||||
buffer: None,
|
||||
detune: *options.detune,
|
||||
loop_enabled: options.loop_,
|
||||
loop_end: Some(*options.loopEnd),
|
||||
loop_start: Some(*options.loopStart),
|
||||
playback_rate: *options.playbackRate,
|
||||
}
|
||||
}
|
||||
}
|
248
components/script/dom/audiocontext.rs
Normal file
248
components/script/dom/audiocontext.rs
Normal file
|
@ -0,0 +1,248 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::baseaudiocontext::{BaseAudioContext, BaseAudioContextOptions};
|
||||
use dom::bindings::codegen::Bindings::AudioContextBinding;
|
||||
use dom::bindings::codegen::Bindings::AudioContextBinding::{AudioContextLatencyCategory, AudioContextMethods};
|
||||
use dom::bindings::codegen::Bindings::AudioContextBinding::{AudioContextOptions, AudioTimestamp};
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::AudioContextState;
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::BaseAudioContextBinding::BaseAudioContextMethods;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||
use dom::bindings::reflector::{DomObject, reflect_dom_object};
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::promise::Promise;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::context::{LatencyCategory, ProcessingState, RealTimeAudioContextOptions};
|
||||
use std::rc::Rc;
|
||||
use task_source::TaskSource;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioContext {
|
||||
context: BaseAudioContext,
|
||||
latency_hint: AudioContextLatencyCategory,
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-audiocontext-baselatency
|
||||
base_latency: f64,
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-audiocontext-outputlatency
|
||||
output_latency: f64,
|
||||
}
|
||||
|
||||
impl AudioContext {
|
||||
#[allow(unrooted_must_root)]
|
||||
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
||||
fn new_inherited(options: &AudioContextOptions) -> AudioContext {
|
||||
// Steps 1-3.
|
||||
let context = BaseAudioContext::new_inherited(
|
||||
BaseAudioContextOptions::AudioContext(options.into()),
|
||||
);
|
||||
|
||||
// Step 4.1.
|
||||
let latency_hint = options.latencyHint;
|
||||
|
||||
// Step 4.2. The sample rate is set during the creation of the BaseAudioContext.
|
||||
// servo-media takes care of setting the default sample rate of the output device
|
||||
// and of resampling the audio output if needed.
|
||||
|
||||
// Steps 5 and 6 of the construction algorithm will happen in `resume`,
|
||||
// after reflecting dom object.
|
||||
|
||||
AudioContext {
|
||||
context,
|
||||
latency_hint,
|
||||
base_latency: 0., // TODO
|
||||
output_latency: 0., // TODO
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(window: &Window, options: &AudioContextOptions) -> DomRoot<AudioContext> {
|
||||
let context = AudioContext::new_inherited(options);
|
||||
let context = reflect_dom_object(Box::new(context), window, AudioContextBinding::Wrap);
|
||||
context.resume();
|
||||
context
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
options: &AudioContextOptions,
|
||||
) -> Fallible<DomRoot<AudioContext>> {
|
||||
Ok(AudioContext::new(window, options))
|
||||
}
|
||||
|
||||
fn resume(&self) {
|
||||
// Step 5.
|
||||
if self.context.is_allowed_to_start() {
|
||||
// Step 6.
|
||||
self.context.resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioContextMethods for AudioContext {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-baselatency
|
||||
fn BaseLatency(&self) -> Finite<f64> {
|
||||
Finite::wrap(self.base_latency)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-outputlatency
|
||||
fn OutputLatency(&self) -> Finite<f64> {
|
||||
Finite::wrap(self.output_latency)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-outputlatency
|
||||
fn GetOutputTimestamp(&self) -> AudioTimestamp {
|
||||
// TODO
|
||||
AudioTimestamp {
|
||||
contextTime: Some(Finite::wrap(0.)),
|
||||
performanceTime: Some(Finite::wrap(0.)),
|
||||
}
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend
|
||||
#[allow(unrooted_must_root)]
|
||||
fn Suspend(&self) -> Rc<Promise> {
|
||||
// Step 1.
|
||||
let promise = Promise::new(&self.global());
|
||||
|
||||
// Step 2.
|
||||
if self.context.control_thread_state() == ProcessingState::Closed {
|
||||
promise.reject_error(Error::InvalidState);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
if self.context.State() == AudioContextState::Suspended {
|
||||
promise.resolve_native(&());
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Steps 4 and 5.
|
||||
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
match self.context.audio_context_impl().suspend() {
|
||||
Ok(_) => {
|
||||
let base_context = Trusted::new(&self.context);
|
||||
let context = Trusted::new(self);
|
||||
let _ = task_source.queue(
|
||||
task!(suspend_ok: move || {
|
||||
let base_context = base_context.root();
|
||||
let context = context.root();
|
||||
let promise = trusted_promise.root();
|
||||
promise.resolve_native(&());
|
||||
if base_context.State() != AudioContextState::Suspended {
|
||||
base_context.set_state_attribute(AudioContextState::Suspended);
|
||||
let window = DomRoot::downcast::<Window>(context.global()).unwrap();
|
||||
window.dom_manipulation_task_source().queue_simple_event(
|
||||
context.upcast(),
|
||||
atom!("statechange"),
|
||||
&window
|
||||
);
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
},
|
||||
Err(_) => {
|
||||
// The spec does not define the error case and `suspend` should
|
||||
// never fail, but we handle the case here for completion.
|
||||
let _ = task_source.queue(
|
||||
task!(suspend_error: move || {
|
||||
let promise = trusted_promise.root();
|
||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
// Step 6.
|
||||
promise
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-close
|
||||
#[allow(unrooted_must_root)]
|
||||
fn Close(&self) -> Rc<Promise> {
|
||||
// Step 1.
|
||||
let promise = Promise::new(&self.global());
|
||||
|
||||
// Step 2.
|
||||
if self.context.control_thread_state() == ProcessingState::Closed {
|
||||
promise.reject_error(Error::InvalidState);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
if self.context.State() == AudioContextState::Closed {
|
||||
promise.resolve_native(&());
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Steps 4 and 5.
|
||||
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
match self.context.audio_context_impl().close() {
|
||||
Ok(_) => {
|
||||
let base_context = Trusted::new(&self.context);
|
||||
let context = Trusted::new(self);
|
||||
let _ = task_source.queue(
|
||||
task!(suspend_ok: move || {
|
||||
let base_context = base_context.root();
|
||||
let context = context.root();
|
||||
let promise = trusted_promise.root();
|
||||
promise.resolve_native(&());
|
||||
if base_context.State() != AudioContextState::Closed {
|
||||
base_context.set_state_attribute(AudioContextState::Closed);
|
||||
let window = DomRoot::downcast::<Window>(context.global()).unwrap();
|
||||
window.dom_manipulation_task_source().queue_simple_event(
|
||||
context.upcast(),
|
||||
atom!("statechange"),
|
||||
&window
|
||||
);
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
},
|
||||
Err(_) => {
|
||||
// The spec does not define the error case and `suspend` should
|
||||
// never fail, but we handle the case here for completion.
|
||||
let _ = task_source.queue(
|
||||
task!(suspend_error: move || {
|
||||
let promise = trusted_promise.root();
|
||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
// Step 6.
|
||||
promise
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AudioContextLatencyCategory> for LatencyCategory {
|
||||
fn from(category: AudioContextLatencyCategory) -> Self {
|
||||
match category {
|
||||
AudioContextLatencyCategory::Balanced => LatencyCategory::Balanced,
|
||||
AudioContextLatencyCategory::Interactive => LatencyCategory::Interactive,
|
||||
AudioContextLatencyCategory::Playback => LatencyCategory::Playback,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a AudioContextOptions> for RealTimeAudioContextOptions {
|
||||
fn from(options: &AudioContextOptions) -> Self {
|
||||
Self {
|
||||
sample_rate: *options.sampleRate.unwrap_or(Finite::wrap(44100.)),
|
||||
latency_hint: options.latencyHint.into(),
|
||||
}
|
||||
}
|
||||
}
|
53
components/script/dom/audiodestinationnode.rs
Normal file
53
components/script/dom/audiodestinationnode.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audionode::{AudioNode, MAX_CHANNEL_COUNT};
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioDestinationNodeBinding::{self, AudioDestinationNodeMethods};
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::node::AudioNodeInit;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioDestinationNode {
|
||||
node: AudioNode,
|
||||
}
|
||||
|
||||
impl AudioDestinationNode {
|
||||
fn new_inherited(
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioNodeOptions,
|
||||
) -> AudioDestinationNode {
|
||||
AudioDestinationNode {
|
||||
node: AudioNode::new_inherited(
|
||||
AudioNodeInit::DestinationNode,
|
||||
Some(context.destination_node()),
|
||||
context,
|
||||
options,
|
||||
1,
|
||||
1,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioNodeOptions,
|
||||
) -> DomRoot<AudioDestinationNode> {
|
||||
let node = AudioDestinationNode::new_inherited(context, options);
|
||||
reflect_dom_object(Box::new(node), global, AudioDestinationNodeBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioDestinationNodeMethods for AudioDestinationNode {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audiodestinationnode-maxchannelcount
|
||||
fn MaxChannelCount(&self) -> u32 {
|
||||
MAX_CHANNEL_COUNT
|
||||
}
|
||||
}
|
285
components/script/dom/audionode.rs
Normal file
285
components/script/dom/audionode.rs
Normal file
|
@ -0,0 +1,285 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audioparam::AudioParam;
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{AudioNodeMethods, AudioNodeOptions};
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
||||
use dom::bindings::codegen::InheritTypes::{AudioNodeTypeId, EventTargetTypeId};
|
||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::graph::NodeId;
|
||||
use servo_media::audio::node::{AudioNodeMessage, AudioNodeInit};
|
||||
use servo_media::audio::node::ChannelCountMode as ServoMediaChannelCountMode;
|
||||
use servo_media::audio::node::ChannelInterpretation as ServoMediaChannelInterpretation;
|
||||
use std::cell::Cell;
|
||||
|
||||
// 32 is the minimum required by the spec for createBuffer() and the deprecated
|
||||
// createScriptProcessor() and matches what is used by Blink and Gecko.
|
||||
// The limit protects against large memory allocations.
|
||||
pub const MAX_CHANNEL_COUNT: u32 = 32;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioNode {
|
||||
eventtarget: EventTarget,
|
||||
#[ignore_malloc_size_of = "servo_media"]
|
||||
node_id: NodeId,
|
||||
context: Dom<BaseAudioContext>,
|
||||
number_of_inputs: u32,
|
||||
number_of_outputs: u32,
|
||||
channel_count: Cell<u32>,
|
||||
channel_count_mode: Cell<ChannelCountMode>,
|
||||
channel_interpretation: Cell<ChannelInterpretation>,
|
||||
}
|
||||
|
||||
impl AudioNode {
|
||||
pub fn new_inherited(
|
||||
node_type: AudioNodeInit,
|
||||
node_id: Option<NodeId>,
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioNodeOptions,
|
||||
number_of_inputs: u32,
|
||||
number_of_outputs: u32,
|
||||
) -> AudioNode {
|
||||
let node_id =
|
||||
node_id.unwrap_or_else(|| context.audio_context_impl().create_node(node_type));
|
||||
AudioNode {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
node_id,
|
||||
context: Dom::from_ref(context),
|
||||
number_of_inputs,
|
||||
number_of_outputs,
|
||||
channel_count: Cell::new(options.channelCount.unwrap_or(2)),
|
||||
channel_count_mode: Cell::new(options.channelCountMode.unwrap_or_default()),
|
||||
channel_interpretation: Cell::new(options.channelInterpretation.unwrap_or_default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message(&self, message: AudioNodeMessage) {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.message_node(self.node_id, message);
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioNodeMethods for AudioNode {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-connect
|
||||
fn Connect(
|
||||
&self,
|
||||
destination: &AudioNode,
|
||||
output: u32,
|
||||
input: u32,
|
||||
) -> Fallible<DomRoot<AudioNode>> {
|
||||
if self.context != destination.context {
|
||||
return Err(Error::InvalidAccess);
|
||||
}
|
||||
|
||||
if output >= self.NumberOfOutputs() || input >= destination.NumberOfInputs() {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
// servo-media takes care of ignoring duplicated connections.
|
||||
|
||||
self.context.audio_context_impl().connect_ports(
|
||||
self.node_id().output(output),
|
||||
destination.node_id().input(input),
|
||||
);
|
||||
|
||||
Ok(DomRoot::from_ref(destination))
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-connect-destinationparam-output
|
||||
fn Connect_(&self, dest: &AudioParam, output: u32) -> Fallible<()> {
|
||||
if self.context != dest.context() {
|
||||
return Err(Error::InvalidAccess);
|
||||
}
|
||||
|
||||
if output >= self.NumberOfOutputs() {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
// servo-media takes care of ignoring duplicated connections.
|
||||
|
||||
self.context.audio_context_impl().connect_ports(
|
||||
self.node_id().output(output),
|
||||
dest.node_id().param(dest.param_type()),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
|
||||
fn Disconnect(&self) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_all_from(self.node_id());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-output
|
||||
fn Disconnect_(&self, out: u32) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_output(self.node_id().output(out));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode
|
||||
fn Disconnect__(&self, to: &AudioNode) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_between(self.node_id(), to.node_id());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output
|
||||
fn Disconnect___(&self, to: &AudioNode, out: u32) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_output_between(self.node_id().output(out), to.node_id());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output-input
|
||||
fn Disconnect____(&self, to: &AudioNode, out: u32, inp: u32) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_output_between_to(self.node_id().output(out), to.node_id().input(inp));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
|
||||
fn Disconnect_____(&self, param: &AudioParam) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_to(self.node_id(),
|
||||
param.node_id().param(param.param_type()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
|
||||
fn Disconnect______(&self, param: &AudioParam, out: u32) -> ErrorResult {
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.disconnect_output_between_to(self.node_id().output(out),
|
||||
param.node_id().param(param.param_type()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-context
|
||||
fn Context(&self) -> DomRoot<BaseAudioContext> {
|
||||
DomRoot::from_ref(&self.context)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-numberofinputs
|
||||
fn NumberOfInputs(&self) -> u32 {
|
||||
self.number_of_inputs
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-numberofoutputs
|
||||
fn NumberOfOutputs(&self) -> u32 {
|
||||
self.number_of_outputs
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelcount
|
||||
fn ChannelCount(&self) -> u32 {
|
||||
self.channel_count.get()
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelcount
|
||||
fn SetChannelCount(&self, value: u32) -> ErrorResult {
|
||||
match self.upcast::<EventTarget>().type_id() {
|
||||
EventTargetTypeId::AudioNode(AudioNodeTypeId::AudioDestinationNode) => {
|
||||
if self.context.is_offline() {
|
||||
return Err(Error::InvalidState);
|
||||
} else if value < 1 || value > MAX_CHANNEL_COUNT {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
},
|
||||
// XXX We do not support any of the other AudioNodes with
|
||||
// constraints yet. Add more cases here as we add support
|
||||
// for new AudioNodes.
|
||||
_ => (),
|
||||
};
|
||||
|
||||
if value == 0 || value > MAX_CHANNEL_COUNT {
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
|
||||
self.channel_count.set(value);
|
||||
self.message(AudioNodeMessage::SetChannelCount(value as u8));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelcountmode
|
||||
fn ChannelCountMode(&self) -> ChannelCountMode {
|
||||
self.channel_count_mode.get()
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelcountmode
|
||||
fn SetChannelCountMode(&self, value: ChannelCountMode) -> ErrorResult {
|
||||
// Channel count mode has no effect for nodes with no inputs.
|
||||
if self.number_of_inputs == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match self.upcast::<EventTarget>().type_id() {
|
||||
EventTargetTypeId::AudioNode(AudioNodeTypeId::AudioDestinationNode) => {
|
||||
if self.context.is_offline() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
},
|
||||
// XXX We do not support any of the other AudioNodes with
|
||||
// constraints yet. Add more cases here as we add support
|
||||
// for new AudioNodes.
|
||||
_ => (),
|
||||
};
|
||||
|
||||
self.channel_count_mode.set(value);
|
||||
self.message(AudioNodeMessage::SetChannelMode(value.into()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelinterpretation
|
||||
fn ChannelInterpretation(&self) -> ChannelInterpretation {
|
||||
self.channel_interpretation.get()
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelinterpretation
|
||||
fn SetChannelInterpretation(&self, value: ChannelInterpretation) {
|
||||
// Channel interpretation mode has no effect for nodes with no inputs.
|
||||
if self.number_of_inputs == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
self.channel_interpretation.set(value);
|
||||
self.message(AudioNodeMessage::SetChannelInterpretation(value.into()));
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ChannelCountMode> for ServoMediaChannelCountMode {
|
||||
fn from(mode: ChannelCountMode) -> Self {
|
||||
match mode {
|
||||
ChannelCountMode::Max => ServoMediaChannelCountMode::Max,
|
||||
ChannelCountMode::Clamped_max => ServoMediaChannelCountMode::ClampedMax,
|
||||
ChannelCountMode::Explicit => ServoMediaChannelCountMode::Explicit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ChannelInterpretation> for ServoMediaChannelInterpretation {
|
||||
fn from(interpretation: ChannelInterpretation) -> Self {
|
||||
match interpretation {
|
||||
ChannelInterpretation::Discrete => ServoMediaChannelInterpretation::Discrete,
|
||||
ChannelInterpretation::Speakers => ServoMediaChannelInterpretation::Speakers,
|
||||
}
|
||||
}
|
||||
}
|
228
components/script/dom/audioparam.rs
Normal file
228
components/script/dom/audioparam.rs
Normal file
|
@ -0,0 +1,228 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioParamBinding;
|
||||
use dom::bindings::codegen::Bindings::AudioParamBinding::{AudioParamMethods, AutomationRate};
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::graph::NodeId;
|
||||
use servo_media::audio::node::AudioNodeMessage;
|
||||
use servo_media::audio::param::{ParamRate, ParamType, RampKind, UserAutomationEvent};
|
||||
use std::cell::Cell;
|
||||
use std::sync::mpsc;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioParam {
|
||||
reflector_: Reflector,
|
||||
context: Dom<BaseAudioContext>,
|
||||
#[ignore_malloc_size_of = "servo_media"]
|
||||
node: NodeId,
|
||||
#[ignore_malloc_size_of = "servo_media"]
|
||||
param: ParamType,
|
||||
automation_rate: Cell<AutomationRate>,
|
||||
default_value: f32,
|
||||
min_value: f32,
|
||||
max_value: f32,
|
||||
}
|
||||
|
||||
impl AudioParam {
|
||||
pub fn new_inherited(
|
||||
context: &BaseAudioContext,
|
||||
node: NodeId,
|
||||
param: ParamType,
|
||||
automation_rate: AutomationRate,
|
||||
default_value: f32,
|
||||
min_value: f32,
|
||||
max_value: f32,
|
||||
) -> AudioParam {
|
||||
AudioParam {
|
||||
reflector_: Reflector::new(),
|
||||
context: Dom::from_ref(context),
|
||||
node,
|
||||
param,
|
||||
automation_rate: Cell::new(automation_rate),
|
||||
default_value,
|
||||
min_value,
|
||||
max_value,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
node: NodeId,
|
||||
param: ParamType,
|
||||
automation_rate: AutomationRate,
|
||||
default_value: f32,
|
||||
min_value: f32,
|
||||
max_value: f32,
|
||||
) -> DomRoot<AudioParam> {
|
||||
let audio_param = AudioParam::new_inherited(
|
||||
context,
|
||||
node,
|
||||
param,
|
||||
automation_rate,
|
||||
default_value,
|
||||
min_value,
|
||||
max_value,
|
||||
);
|
||||
reflect_dom_object(Box::new(audio_param), window, AudioParamBinding::Wrap)
|
||||
}
|
||||
|
||||
fn message_node(&self, message: AudioNodeMessage) {
|
||||
self.context.audio_context_impl().message_node(self.node, message);
|
||||
}
|
||||
|
||||
pub fn context(&self) -> &BaseAudioContext {
|
||||
&self.context
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node
|
||||
}
|
||||
|
||||
pub fn param_type(&self) -> ParamType {
|
||||
self.param
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioParamMethods for AudioParam {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-automationrate
|
||||
fn AutomationRate(&self) -> AutomationRate {
|
||||
self.automation_rate.get()
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-automationrate
|
||||
fn SetAutomationRate(&self, automation_rate: AutomationRate) {
|
||||
self.automation_rate.set(automation_rate);
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParamRate(self.param, automation_rate.into())
|
||||
);
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-value
|
||||
fn Value(&self) -> Finite<f32> {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
self.message_node(
|
||||
AudioNodeMessage::GetParamValue(self.param, tx)
|
||||
);
|
||||
Finite::wrap(rx.recv().unwrap())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-value
|
||||
fn SetValue(&self, value: Finite<f32>) {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(self.param, UserAutomationEvent::SetValue(*value)),
|
||||
);
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-defaultvalue
|
||||
fn DefaultValue(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.default_value)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-minvalue
|
||||
fn MinValue(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.min_value)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-maxvalue
|
||||
fn MaxValue(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.max_value)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-setvalueattime
|
||||
fn SetValueAtTime(&self, value: Finite<f32>, start_time: Finite<f64>) -> DomRoot<AudioParam> {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(
|
||||
self.param,
|
||||
UserAutomationEvent::SetValueAtTime(*value, *start_time),
|
||||
)
|
||||
);
|
||||
DomRoot::from_ref(self)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-linearramptovalueattime
|
||||
fn LinearRampToValueAtTime(
|
||||
&self,
|
||||
value: Finite<f32>,
|
||||
end_time: Finite<f64>,
|
||||
) -> DomRoot<AudioParam> {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(
|
||||
self.param,
|
||||
UserAutomationEvent::RampToValueAtTime(RampKind::Linear, *value, *end_time),
|
||||
),
|
||||
);
|
||||
DomRoot::from_ref(self)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-exponentialramptovalueattime
|
||||
fn ExponentialRampToValueAtTime(
|
||||
&self,
|
||||
value: Finite<f32>,
|
||||
end_time: Finite<f64>,
|
||||
) -> DomRoot<AudioParam> {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(
|
||||
self.param,
|
||||
UserAutomationEvent::RampToValueAtTime(RampKind::Exponential, *value, *end_time),
|
||||
),
|
||||
);
|
||||
DomRoot::from_ref(self)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-settargetattime
|
||||
fn SetTargetAtTime(
|
||||
&self,
|
||||
target: Finite<f32>,
|
||||
start_time: Finite<f64>,
|
||||
time_constant: Finite<f32>,
|
||||
) -> DomRoot<AudioParam> {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(
|
||||
self.param,
|
||||
UserAutomationEvent::SetTargetAtTime(*target, *start_time, (*time_constant).into()),
|
||||
),
|
||||
);
|
||||
DomRoot::from_ref(self)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-cancelscheduledvalues
|
||||
fn CancelScheduledValues(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(
|
||||
self.param,
|
||||
UserAutomationEvent::CancelScheduledValues(*cancel_time),
|
||||
),
|
||||
);
|
||||
DomRoot::from_ref(self)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioparam-cancelandholdattime
|
||||
fn CancelAndHoldAtTime(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
|
||||
self.message_node(
|
||||
AudioNodeMessage::SetParam(
|
||||
self.param,
|
||||
UserAutomationEvent::CancelAndHoldAtTime(*cancel_time),
|
||||
),
|
||||
);
|
||||
DomRoot::from_ref(self)
|
||||
}
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#enumdef-automationrate
|
||||
impl From<AutomationRate> for ParamRate {
|
||||
fn from(rate: AutomationRate) -> Self {
|
||||
match rate {
|
||||
AutomationRate::A_rate => ParamRate::ARate,
|
||||
AutomationRate::K_rate => ParamRate::KRate,
|
||||
}
|
||||
}
|
||||
}
|
112
components/script/dom/audioscheduledsourcenode.rs
Normal file
112
components/script/dom/audioscheduledsourcenode.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
use dom::audionode::AudioNode;
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||
use dom::bindings::codegen::Bindings::AudioScheduledSourceNodeBinding::AudioScheduledSourceNodeMethods;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::node::{AudioNodeMessage, AudioNodeInit, AudioScheduledSourceNodeMessage};
|
||||
use servo_media::audio::node::OnEndedCallback;
|
||||
use std::cell::Cell;
|
||||
use task_source::{TaskSource, TaskSourceName};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct AudioScheduledSourceNode {
|
||||
node: AudioNode,
|
||||
started: Cell<bool>,
|
||||
stopped: Cell<bool>,
|
||||
}
|
||||
|
||||
impl AudioScheduledSourceNode {
|
||||
pub fn new_inherited(
|
||||
node_type: AudioNodeInit,
|
||||
context: &BaseAudioContext,
|
||||
options: &AudioNodeOptions,
|
||||
number_of_inputs: u32,
|
||||
number_of_outputs: u32,
|
||||
) -> AudioScheduledSourceNode {
|
||||
AudioScheduledSourceNode {
|
||||
node: AudioNode::new_inherited(
|
||||
node_type,
|
||||
None, /* node_id */
|
||||
context,
|
||||
options,
|
||||
number_of_inputs,
|
||||
number_of_outputs,
|
||||
),
|
||||
started: Cell::new(false),
|
||||
stopped: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node(&self) -> &AudioNode {
|
||||
&self.node
|
||||
}
|
||||
|
||||
pub fn started(&self) -> bool {
|
||||
self.started.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioScheduledSourceNodeMethods for AudioScheduledSourceNode {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioscheduledsourcenode-onended
|
||||
event_handler!(ended, GetOnended, SetOnended);
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioscheduledsourcenode-start
|
||||
fn Start(&self, when: Finite<f64>) -> Fallible<()> {
|
||||
if self.started.get() || self.stopped.get() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let canceller = window.task_canceller(TaskSourceName::DOMManipulation);
|
||||
let callback = OnEndedCallback::new(move || {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(ended: move || {
|
||||
let this = this.root();
|
||||
let global = this.global();
|
||||
let window = global.as_window();
|
||||
window.dom_manipulation_task_source().queue_simple_event(
|
||||
this.upcast(),
|
||||
atom!("ended"),
|
||||
&window
|
||||
);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
});
|
||||
|
||||
self.node().message(
|
||||
AudioNodeMessage::AudioScheduledSourceNode(
|
||||
AudioScheduledSourceNodeMessage::RegisterOnEndedCallback(callback)));
|
||||
|
||||
self.started.set(true);
|
||||
self.node
|
||||
.message(AudioNodeMessage::AudioScheduledSourceNode(
|
||||
AudioScheduledSourceNodeMessage::Start(*when),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-audioscheduledsourcenode-stop
|
||||
fn Stop(&self, when: Finite<f64>) -> Fallible<()> {
|
||||
if !self.started.get() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
self.stopped.set(true);
|
||||
self.node
|
||||
.message(AudioNodeMessage::AudioScheduledSourceNode(
|
||||
AudioScheduledSourceNodeMessage::Stop(*when),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
}
|
463
components/script/dom/baseaudiocontext.rs
Normal file
463
components/script/dom/baseaudiocontext.rs
Normal file
|
@ -0,0 +1,463 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audiobuffer::AudioBuffer;
|
||||
use dom::audiobuffersourcenode::AudioBufferSourceNode;
|
||||
use dom::audiodestinationnode::AudioDestinationNode;
|
||||
use dom::audionode::MAX_CHANNEL_COUNT;
|
||||
use dom::bindings::callback::ExceptionHandling;
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::AudioBufferSourceNodeBinding::AudioBufferSourceOptions;
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::AudioContextState;
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::BaseAudioContextMethods;
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeErrorCallback;
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeSuccessCallback;
|
||||
use dom::bindings::codegen::Bindings::GainNodeBinding::GainOptions;
|
||||
use dom::bindings::codegen::Bindings::OscillatorNodeBinding::OscillatorOptions;
|
||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::root::{DomRoot, MutNullableDom};
|
||||
use dom::domexception::{DOMErrorName, DOMException};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::gainnode::GainNode;
|
||||
use dom::oscillatornode::OscillatorNode;
|
||||
use dom::promise::Promise;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use js::rust::CustomAutoRooterGuard;
|
||||
use js::typedarray::ArrayBuffer;
|
||||
use servo_media::{Backend, ServoMedia};
|
||||
use servo_media::audio::context::{AudioContext, AudioContextOptions, ProcessingState};
|
||||
use servo_media::audio::context::{OfflineAudioContextOptions, RealTimeAudioContextOptions};
|
||||
use servo_media::audio::decoder::AudioDecoderCallbacks;
|
||||
use servo_media::audio::graph::NodeId;
|
||||
use std::cell::Cell;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use task_source::{TaskSource, TaskSourceName};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum BaseAudioContextOptions {
|
||||
AudioContext(RealTimeAudioContextOptions),
|
||||
OfflineAudioContext(OfflineAudioContextOptions),
|
||||
}
|
||||
|
||||
#[must_root]
|
||||
#[derive(JSTraceable)]
|
||||
struct DecodeResolver {
|
||||
pub promise: Rc<Promise>,
|
||||
pub success_callback: Option<Rc<DecodeSuccessCallback>>,
|
||||
pub error_callback: Option<Rc<DecodeErrorCallback>>,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
pub struct BaseAudioContext {
|
||||
eventtarget: EventTarget,
|
||||
#[ignore_malloc_size_of = "servo_media"]
|
||||
audio_context_impl: Rc<AudioContext<Backend>>,
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination
|
||||
destination: MutNullableDom<AudioDestinationNode>,
|
||||
/// Resume promises which are soon to be fulfilled by a queued task.
|
||||
#[ignore_malloc_size_of = "promises are hard"]
|
||||
in_flight_resume_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>,
|
||||
/// https://webaudio.github.io/web-audio-api/#pendingresumepromises
|
||||
#[ignore_malloc_size_of = "promises are hard"]
|
||||
pending_resume_promises: DomRefCell<Vec<Rc<Promise>>>,
|
||||
#[ignore_malloc_size_of = "promises are hard"]
|
||||
decode_resolvers: DomRefCell<HashMap<String, DecodeResolver>>,
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-samplerate
|
||||
sample_rate: f32,
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-state
|
||||
/// Although servo-media already keeps track of the control thread state,
|
||||
/// we keep a state flag here as well. This is so that we can synchronously
|
||||
/// throw when trying to do things on the context when the context has just
|
||||
/// been "closed()".
|
||||
state: Cell<AudioContextState>,
|
||||
channel_count: u32,
|
||||
}
|
||||
|
||||
impl BaseAudioContext {
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new_inherited(options: BaseAudioContextOptions) -> BaseAudioContext {
|
||||
let (sample_rate, channel_count) = match options {
|
||||
BaseAudioContextOptions::AudioContext(ref opt) => (opt.sample_rate, 2),
|
||||
BaseAudioContextOptions::OfflineAudioContext(ref opt) => (opt.sample_rate, opt.channels),
|
||||
};
|
||||
|
||||
let context = BaseAudioContext {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
audio_context_impl: Rc::new(
|
||||
ServoMedia::get()
|
||||
.unwrap()
|
||||
.create_audio_context(options.into()),
|
||||
),
|
||||
destination: Default::default(),
|
||||
in_flight_resume_promises_queue: Default::default(),
|
||||
pending_resume_promises: Default::default(),
|
||||
decode_resolvers: Default::default(),
|
||||
sample_rate,
|
||||
state: Cell::new(AudioContextState::Suspended),
|
||||
channel_count: channel_count.into(),
|
||||
};
|
||||
|
||||
context
|
||||
}
|
||||
|
||||
/// Tells whether this is an OfflineAudioContext or not.
|
||||
pub fn is_offline(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn audio_context_impl(&self) -> Rc<AudioContext<Backend>> {
|
||||
self.audio_context_impl.clone()
|
||||
}
|
||||
|
||||
pub fn destination_node(&self) -> NodeId {
|
||||
self.audio_context_impl.dest_node()
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#allowed-to-start
|
||||
pub fn is_allowed_to_start(&self) -> bool {
|
||||
self.state.get() == AudioContextState::Suspended
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
fn push_pending_resume_promise(&self, promise: &Rc<Promise>) {
|
||||
self.pending_resume_promises
|
||||
.borrow_mut()
|
||||
.push(promise.clone());
|
||||
}
|
||||
|
||||
/// Takes the pending resume promises.
|
||||
///
|
||||
/// The result with which these promises will be fulfilled is passed here
|
||||
/// and this method returns nothing because we actually just move the
|
||||
/// current list of pending resume promises to the
|
||||
/// `in_flight_resume_promises_queue` field.
|
||||
///
|
||||
/// Each call to this method must be followed by a call to
|
||||
/// `fulfill_in_flight_resume_promises`, to actually fulfill the promises
|
||||
/// which were taken and moved to the in-flight queue.
|
||||
#[allow(unrooted_must_root)]
|
||||
fn take_pending_resume_promises(&self, result: ErrorResult) {
|
||||
let pending_resume_promises =
|
||||
mem::replace(&mut *self.pending_resume_promises.borrow_mut(), vec![]);
|
||||
self.in_flight_resume_promises_queue
|
||||
.borrow_mut()
|
||||
.push_back((pending_resume_promises.into(), result));
|
||||
}
|
||||
|
||||
/// Fulfills the next in-flight resume promises queue after running a closure.
|
||||
///
|
||||
/// See the comment on `take_pending_resume_promises` for why this method
|
||||
/// does not take a list of promises to fulfill. Callers cannot just pop
|
||||
/// the front list off of `in_flight_resume_promises_queue` and later fulfill
|
||||
/// the promises because that would mean putting
|
||||
/// `#[allow(unrooted_must_root)]` on even more functions, potentially
|
||||
/// hiding actual safety bugs.
|
||||
#[allow(unrooted_must_root)]
|
||||
fn fulfill_in_flight_resume_promises<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce(),
|
||||
{
|
||||
let (promises, result) = self
|
||||
.in_flight_resume_promises_queue
|
||||
.borrow_mut()
|
||||
.pop_front()
|
||||
.expect("there should be at least one list of in flight resume promises");
|
||||
f();
|
||||
for promise in &*promises {
|
||||
match result {
|
||||
Ok(ref value) => promise.resolve_native(value),
|
||||
Err(ref error) => promise.reject_error(error.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Control thread processing state
|
||||
pub fn control_thread_state(&self) -> ProcessingState {
|
||||
self.audio_context_impl.state()
|
||||
}
|
||||
|
||||
/// Set audio context state
|
||||
pub fn set_state_attribute(&self, state: AudioContextState) {
|
||||
self.state.set(state);
|
||||
}
|
||||
|
||||
pub fn resume(&self) {
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
// Set the rendering thread state to 'running' and start
|
||||
// rendering the audio graph.
|
||||
match self.audio_context_impl.resume() {
|
||||
Ok(()) => {
|
||||
self.take_pending_resume_promises(Ok(()));
|
||||
let _ = task_source.queue(
|
||||
task!(resume_success: move || {
|
||||
let this = this.root();
|
||||
this.fulfill_in_flight_resume_promises(|| {
|
||||
if this.state.get() != AudioContextState::Running {
|
||||
this.state.set(AudioContextState::Running);
|
||||
let window = DomRoot::downcast::<Window>(this.global()).unwrap();
|
||||
window.dom_manipulation_task_source().queue_simple_event(
|
||||
this.upcast(),
|
||||
atom!("statechange"),
|
||||
&window
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
},
|
||||
Err(()) => {
|
||||
self.take_pending_resume_promises(Err(Error::Type(
|
||||
"Something went wrong".to_owned(),
|
||||
)));
|
||||
let _ = task_source.queue(
|
||||
task!(resume_error: move || {
|
||||
this.root().fulfill_in_flight_resume_promises(|| {})
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseAudioContextMethods for BaseAudioContext {
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-samplerate
|
||||
fn SampleRate(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.sample_rate)
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-currenttime
|
||||
fn CurrentTime(&self) -> Finite<f64> {
|
||||
let current_time = self.audio_context_impl.current_time();
|
||||
Finite::wrap(current_time)
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-state
|
||||
fn State(&self) -> AudioContextState {
|
||||
self.state.get()
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-resume
|
||||
#[allow(unrooted_must_root)]
|
||||
fn Resume(&self) -> Rc<Promise> {
|
||||
// Step 1.
|
||||
let promise = Promise::new(&self.global());
|
||||
|
||||
// Step 2.
|
||||
if self.audio_context_impl.state() == ProcessingState::Closed {
|
||||
promise.reject_error(Error::InvalidState);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
if self.state.get() == AudioContextState::Running {
|
||||
promise.resolve_native(&());
|
||||
return promise;
|
||||
}
|
||||
|
||||
self.push_pending_resume_promise(&promise);
|
||||
|
||||
// Step 4.
|
||||
if !self.is_allowed_to_start() {
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Steps 5 and 6.
|
||||
self.resume();
|
||||
|
||||
// Step 7.
|
||||
promise
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination
|
||||
fn Destination(&self) -> DomRoot<AudioDestinationNode> {
|
||||
let global = self.global();
|
||||
self.destination.or_init(|| {
|
||||
let mut options = AudioNodeOptions::empty();
|
||||
options.channelCount = Some(self.channel_count);
|
||||
options.channelCountMode = Some(ChannelCountMode::Explicit);
|
||||
options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
||||
AudioDestinationNode::new(&global, self, &options)
|
||||
})
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-onstatechange
|
||||
event_handler!(statechange, GetOnstatechange, SetOnstatechange);
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createoscillator
|
||||
fn CreateOscillator(&self) -> DomRoot<OscillatorNode> {
|
||||
OscillatorNode::new(
|
||||
&self.global().as_window(),
|
||||
&self,
|
||||
&OscillatorOptions::empty(),
|
||||
)
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-creategain
|
||||
fn CreateGain(&self) -> DomRoot<GainNode> {
|
||||
GainNode::new(&self.global().as_window(), &self, &GainOptions::empty())
|
||||
}
|
||||
|
||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer
|
||||
fn CreateBuffer(
|
||||
&self,
|
||||
number_of_channels: u32,
|
||||
length: u32,
|
||||
sample_rate: Finite<f32>,
|
||||
) -> Fallible<DomRoot<AudioBuffer>> {
|
||||
if number_of_channels <= 0 ||
|
||||
number_of_channels > MAX_CHANNEL_COUNT ||
|
||||
length <= 0 ||
|
||||
*sample_rate <= 0.
|
||||
{
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
Ok(AudioBuffer::new(
|
||||
&self.global().as_window(),
|
||||
number_of_channels,
|
||||
length,
|
||||
*sample_rate,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffersource
|
||||
fn CreateBufferSource(&self) -> DomRoot<AudioBufferSourceNode> {
|
||||
AudioBufferSourceNode::new(
|
||||
&self.global().as_window(),
|
||||
&self,
|
||||
&AudioBufferSourceOptions::empty(),
|
||||
)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-decodeaudiodata
|
||||
#[allow(unrooted_must_root)]
|
||||
fn DecodeAudioData(
|
||||
&self,
|
||||
audio_data: CustomAutoRooterGuard<ArrayBuffer>,
|
||||
decode_success_callback: Option<Rc<DecodeSuccessCallback>>,
|
||||
decode_error_callback: Option<Rc<DecodeErrorCallback>>,
|
||||
) -> Rc<Promise> {
|
||||
// Step 1.
|
||||
let promise = Promise::new(&self.global());
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
|
||||
if audio_data.len() > 0 {
|
||||
// Step 2.
|
||||
// XXX detach array buffer.
|
||||
let uuid = Uuid::new_v4().simple().to_string();
|
||||
let uuid_ = uuid.clone();
|
||||
self.decode_resolvers.borrow_mut().insert(
|
||||
uuid.clone(),
|
||||
DecodeResolver {
|
||||
promise: promise.clone(),
|
||||
success_callback: decode_success_callback,
|
||||
error_callback: decode_error_callback,
|
||||
},
|
||||
);
|
||||
let audio_data = audio_data.to_vec();
|
||||
let decoded_audio = Arc::new(Mutex::new(Vec::new()));
|
||||
let decoded_audio_ = decoded_audio.clone();
|
||||
let this = Trusted::new(self);
|
||||
let this_ = this.clone();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let task_source_ = window.dom_manipulation_task_source();
|
||||
let canceller = window.task_canceller(TaskSourceName::DOMManipulation);
|
||||
let canceller_ = window.task_canceller(TaskSourceName::DOMManipulation);
|
||||
let callbacks = AudioDecoderCallbacks::new()
|
||||
.eos(move || {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(audio_decode_eos: move || {
|
||||
let this = this.root();
|
||||
let decoded_audio = decoded_audio.lock().unwrap();
|
||||
let buffer = AudioBuffer::new(
|
||||
&this.global().as_window(),
|
||||
1, // XXX servo-media should provide this info
|
||||
decoded_audio.len() as u32,
|
||||
this.sample_rate,
|
||||
Some(decoded_audio.as_slice()));
|
||||
let mut resolvers = this.decode_resolvers.borrow_mut();
|
||||
assert!(resolvers.contains_key(&uuid_));
|
||||
let resolver = resolvers.remove(&uuid_).unwrap();
|
||||
if let Some(callback) = resolver.success_callback {
|
||||
let _ = callback.Call__(&buffer, ExceptionHandling::Report);
|
||||
}
|
||||
resolver.promise.resolve_native(&buffer);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
})
|
||||
.error(move || {
|
||||
let _ = task_source_.queue_with_canceller(
|
||||
task!(audio_decode_eos: move || {
|
||||
let this = this_.root();
|
||||
let mut resolvers = this.decode_resolvers.borrow_mut();
|
||||
assert!(resolvers.contains_key(&uuid));
|
||||
let resolver = resolvers.remove(&uuid).unwrap();
|
||||
if let Some(callback) = resolver.error_callback {
|
||||
let _ = callback.Call__(
|
||||
&DOMException::new(&this.global(), DOMErrorName::DataCloneError),
|
||||
ExceptionHandling::Report);
|
||||
}
|
||||
resolver.promise.reject_error(Error::Type("Audio decode error".to_owned()));
|
||||
}),
|
||||
&canceller_,
|
||||
);
|
||||
})
|
||||
.progress(move |buffer| {
|
||||
decoded_audio_
|
||||
.lock()
|
||||
.unwrap()
|
||||
.extend_from_slice((*buffer).as_ref());
|
||||
})
|
||||
.build();
|
||||
self.audio_context_impl
|
||||
.decode_audio_data(audio_data, callbacks);
|
||||
} else {
|
||||
// Step 3.
|
||||
promise.reject_error(Error::DataClone);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
promise
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BaseAudioContextOptions> for AudioContextOptions {
|
||||
fn from(options: BaseAudioContextOptions) -> Self {
|
||||
match options {
|
||||
BaseAudioContextOptions::AudioContext(options) =>
|
||||
AudioContextOptions::RealTimeAudioContext(options),
|
||||
BaseAudioContextOptions::OfflineAudioContext(options) =>
|
||||
AudioContextOptions::OfflineAudioContext(options),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProcessingState> for AudioContextState {
|
||||
fn from(state: ProcessingState) -> Self {
|
||||
match state {
|
||||
ProcessingState::Suspended => AudioContextState::Suspended,
|
||||
ProcessingState::Running => AudioContextState::Running,
|
||||
ProcessingState::Closed => AudioContextState::Closed,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -423,6 +423,13 @@ impl<T> PartialEq for Dom<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: DomObject> PartialEq<&'a T> for Dom<T> {
|
||||
fn eq(&self, other: &&'a T) -> bool {
|
||||
*self == Dom::from_ref(*other)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> Eq for Dom<T> {}
|
||||
|
||||
impl<T> PartialEq for LayoutDom<T> {
|
||||
|
|
|
@ -90,6 +90,11 @@ use selectors::matching::ElementSelectorFlags;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_atoms::Atom;
|
||||
use servo_media::Backend;
|
||||
use servo_media::audio::buffer_source_node::AudioBuffer;
|
||||
use servo_media::audio::context::AudioContext;
|
||||
use servo_media::audio::graph::NodeId;
|
||||
use servo_media::audio::param::ParamType;
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
use smallvec::SmallVec;
|
||||
use std::cell::{Cell, RefCell, UnsafeCell};
|
||||
|
@ -429,6 +434,10 @@ unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
|||
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
||||
unsafe_no_jsmanaged_fields!(CanvasId);
|
||||
unsafe_no_jsmanaged_fields!(SourceSet);
|
||||
unsafe_no_jsmanaged_fields!(AudioBuffer);
|
||||
unsafe_no_jsmanaged_fields!(AudioContext<Backend>);
|
||||
unsafe_no_jsmanaged_fields!(NodeId);
|
||||
unsafe_no_jsmanaged_fields!(ParamType);
|
||||
|
||||
unsafe impl<'a> JSTraceable for &'a str {
|
||||
#[inline]
|
||||
|
|
95
components/script/dom/gainnode.rs
Normal file
95
components/script/dom/gainnode.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audionode::AudioNode;
|
||||
use dom::audioparam::AudioParam;
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||
use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
|
||||
use dom::bindings::codegen::Bindings::GainNodeBinding::{self, GainNodeMethods, GainOptions};
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::gain_node::GainNodeOptions;
|
||||
use servo_media::audio::node::AudioNodeInit;
|
||||
use servo_media::audio::param::ParamType;
|
||||
use std::f32;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GainNode {
|
||||
node: AudioNode,
|
||||
gain: Dom<AudioParam>,
|
||||
}
|
||||
|
||||
impl GainNode {
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new_inherited(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
gain_options: &GainOptions,
|
||||
) -> GainNode {
|
||||
let mut node_options = AudioNodeOptions::empty();
|
||||
node_options.channelCount = Some(2);
|
||||
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
||||
node_options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
||||
let node = AudioNode::new_inherited(
|
||||
AudioNodeInit::GainNode(gain_options.into()),
|
||||
None,
|
||||
context,
|
||||
&node_options,
|
||||
1, // inputs
|
||||
1, // outputs
|
||||
);
|
||||
let gain = AudioParam::new(
|
||||
window,
|
||||
context,
|
||||
node.node_id(),
|
||||
ParamType::Gain,
|
||||
AutomationRate::A_rate,
|
||||
1., // default value
|
||||
f32::MIN, // min value
|
||||
f32::MAX, // max value
|
||||
);
|
||||
GainNode {
|
||||
node,
|
||||
gain: Dom::from_ref(&gain),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &GainOptions,
|
||||
) -> DomRoot<GainNode> {
|
||||
let node = GainNode::new_inherited(window, context, options);
|
||||
reflect_dom_object(Box::new(node), window, GainNodeBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &GainOptions,
|
||||
) -> Fallible<DomRoot<GainNode>> {
|
||||
Ok(GainNode::new(window, context, options))
|
||||
}
|
||||
}
|
||||
|
||||
impl GainNodeMethods for GainNode {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-gainnode-gain
|
||||
fn Gain(&self) -> DomRoot<AudioParam> {
|
||||
DomRoot::from_ref(&self.gain)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a GainOptions> for GainNodeOptions {
|
||||
fn from(options: &'a GainOptions) -> Self {
|
||||
Self {
|
||||
gain: *options.gain,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -629,3 +629,4 @@ macro_rules! handle_potential_webgl_error {
|
|||
handle_potential_webgl_error!($context, $call, ());
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -216,6 +216,14 @@ pub mod abstractworker;
|
|||
pub mod abstractworkerglobalscope;
|
||||
pub mod activation;
|
||||
pub mod attr;
|
||||
pub mod audiobuffer;
|
||||
pub mod audiobuffersourcenode;
|
||||
pub mod audiocontext;
|
||||
pub mod audiodestinationnode;
|
||||
pub mod audionode;
|
||||
pub mod audioparam;
|
||||
pub mod audioscheduledsourcenode;
|
||||
pub mod baseaudiocontext;
|
||||
pub mod beforeunloadevent;
|
||||
pub mod bindings;
|
||||
pub mod blob;
|
||||
|
@ -290,6 +298,7 @@ pub mod filereader;
|
|||
pub mod filereadersync;
|
||||
pub mod focusevent;
|
||||
pub mod formdata;
|
||||
pub mod gainnode;
|
||||
pub mod gamepad;
|
||||
pub mod gamepadbutton;
|
||||
pub mod gamepadbuttonlist;
|
||||
|
@ -392,6 +401,9 @@ pub mod navigatorinfo;
|
|||
pub mod node;
|
||||
pub mod nodeiterator;
|
||||
pub mod nodelist;
|
||||
pub mod offlineaudiocompletionevent;
|
||||
pub mod offlineaudiocontext;
|
||||
pub mod oscillatornode;
|
||||
pub mod pagetransitionevent;
|
||||
pub mod paintrenderingcontext2d;
|
||||
pub mod paintsize;
|
||||
|
|
77
components/script/dom/offlineaudiocompletionevent.rs
Normal file
77
components/script/dom/offlineaudiocompletionevent.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audiobuffer::AudioBuffer;
|
||||
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
|
||||
use dom::bindings::codegen::Bindings::OfflineAudioCompletionEventBinding;
|
||||
use dom::bindings::codegen::Bindings::OfflineAudioCompletionEventBinding::OfflineAudioCompletionEventInit;
|
||||
use dom::bindings::codegen::Bindings::OfflineAudioCompletionEventBinding::OfflineAudioCompletionEventMethods;
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::{Dom, DomRoot, RootedReference};
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_atoms::Atom;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OfflineAudioCompletionEvent {
|
||||
event: Event,
|
||||
rendered_buffer: Dom<AudioBuffer>,
|
||||
}
|
||||
|
||||
impl OfflineAudioCompletionEvent {
|
||||
pub fn new_inherited(rendered_buffer: &AudioBuffer) -> OfflineAudioCompletionEvent {
|
||||
OfflineAudioCompletionEvent {
|
||||
event: Event::new_inherited(),
|
||||
rendered_buffer: Dom::from_ref(rendered_buffer),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
type_: Atom,
|
||||
bubbles: EventBubbles,
|
||||
cancelable: EventCancelable,
|
||||
rendered_buffer: &AudioBuffer,
|
||||
) -> DomRoot<OfflineAudioCompletionEvent> {
|
||||
let event = Box::new(OfflineAudioCompletionEvent::new_inherited(rendered_buffer));
|
||||
let ev = reflect_dom_object(event, window, OfflineAudioCompletionEventBinding::Wrap);
|
||||
{
|
||||
let event = ev.upcast::<Event>();
|
||||
event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
|
||||
}
|
||||
ev
|
||||
}
|
||||
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
type_: DOMString,
|
||||
init: &OfflineAudioCompletionEventInit,
|
||||
) -> Fallible<DomRoot<OfflineAudioCompletionEvent>> {
|
||||
let bubbles = EventBubbles::from(init.parent.bubbles);
|
||||
let cancelable = EventCancelable::from(init.parent.cancelable);
|
||||
Ok(OfflineAudioCompletionEvent::new(
|
||||
window,
|
||||
Atom::from(type_),
|
||||
bubbles,
|
||||
cancelable,
|
||||
init.renderedBuffer.r(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl OfflineAudioCompletionEventMethods for OfflineAudioCompletionEvent {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocompletionevent-renderedbuffer
|
||||
fn RenderedBuffer(&self) -> DomRoot<AudioBuffer> {
|
||||
DomRoot::from_ref(&*self.rendered_buffer)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-istrusted
|
||||
fn IsTrusted(&self) -> bool {
|
||||
self.event.IsTrusted()
|
||||
}
|
||||
}
|
174
components/script/dom/offlineaudiocontext.rs
Normal file
174
components/script/dom/offlineaudiocontext.rs
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audiobuffer::{AudioBuffer, MAX_SAMPLE_RATE, MIN_SAMPLE_RATE};
|
||||
use dom::audionode::MAX_CHANNEL_COUNT;
|
||||
use dom::baseaudiocontext::{BaseAudioContext, BaseAudioContextOptions};
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::BaseAudioContextBinding::BaseAudioContextMethods;
|
||||
use dom::bindings::codegen::Bindings::OfflineAudioContextBinding;
|
||||
use dom::bindings::codegen::Bindings::OfflineAudioContextBinding::OfflineAudioContextMethods;
|
||||
use dom::bindings::codegen::Bindings::OfflineAudioContextBinding::OfflineAudioContextOptions;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::{DomObject, reflect_dom_object};
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::offlineaudiocompletionevent::OfflineAudioCompletionEvent;
|
||||
use dom::promise::Promise;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::context::OfflineAudioContextOptions as ServoMediaOfflineAudioContextOptions;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::mpsc;
|
||||
use std::thread::Builder;
|
||||
use task_source::{TaskSource, TaskSourceName};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OfflineAudioContext {
|
||||
context: BaseAudioContext,
|
||||
channel_count: u32,
|
||||
length: u32,
|
||||
rendering_started: Cell<bool>,
|
||||
#[ignore_malloc_size_of = "promises are hard"]
|
||||
pending_rendering_promise: DomRefCell<Option<Rc<Promise>>>,
|
||||
}
|
||||
|
||||
impl OfflineAudioContext {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn new_inherited(channel_count: u32,
|
||||
length: u32,
|
||||
sample_rate: f32) -> OfflineAudioContext {
|
||||
let options = ServoMediaOfflineAudioContextOptions {
|
||||
channels: channel_count as u8,
|
||||
length: length as usize,
|
||||
sample_rate,
|
||||
};
|
||||
let context = BaseAudioContext::new_inherited(
|
||||
BaseAudioContextOptions::OfflineAudioContext(options),
|
||||
);
|
||||
OfflineAudioContext {
|
||||
context,
|
||||
channel_count,
|
||||
length,
|
||||
rendering_started: Cell::new(false),
|
||||
pending_rendering_promise: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
fn new(window: &Window,
|
||||
channel_count: u32,
|
||||
length: u32,
|
||||
sample_rate: f32) -> DomRoot<OfflineAudioContext> {
|
||||
let context = OfflineAudioContext::new_inherited(channel_count, length, sample_rate);
|
||||
reflect_dom_object(Box::new(context), window, OfflineAudioContextBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
options: &OfflineAudioContextOptions,
|
||||
) -> Fallible<DomRoot<OfflineAudioContext>> {
|
||||
Ok(OfflineAudioContext::new(window, options.numberOfChannels, options.length, *options.sampleRate))
|
||||
}
|
||||
|
||||
pub fn Constructor_(
|
||||
window: &Window,
|
||||
number_of_channels: u32,
|
||||
length: u32,
|
||||
sample_rate: Finite<f32>,
|
||||
) -> Fallible<DomRoot<OfflineAudioContext>> {
|
||||
if number_of_channels > MAX_CHANNEL_COUNT ||
|
||||
number_of_channels <= 0 ||
|
||||
length <= 0 ||
|
||||
*sample_rate < MIN_SAMPLE_RATE ||
|
||||
*sample_rate > MAX_SAMPLE_RATE
|
||||
{
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
|
||||
Ok(OfflineAudioContext::new(window, number_of_channels, length, *sample_rate))
|
||||
}
|
||||
}
|
||||
|
||||
impl OfflineAudioContextMethods for OfflineAudioContext {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-oncomplete
|
||||
event_handler!(complete, GetOncomplete, SetOncomplete);
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-length
|
||||
fn Length(&self) -> u32 {
|
||||
self.length
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering
|
||||
#[allow(unrooted_must_root)]
|
||||
fn StartRendering(&self) -> Rc<Promise> {
|
||||
let promise = Promise::new(&self.global());
|
||||
if self.rendering_started.get() {
|
||||
promise.reject_error(Error::InvalidState);
|
||||
return promise;
|
||||
}
|
||||
self.rendering_started.set(true);
|
||||
|
||||
*self.pending_rendering_promise.borrow_mut() = Some(promise.clone());
|
||||
|
||||
let processed_audio = Arc::new(Mutex::new(Vec::new()));
|
||||
let processed_audio_ = processed_audio.clone();
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let sender = Mutex::new(sender);
|
||||
self.context
|
||||
.audio_context_impl()
|
||||
.set_eos_callback(Box::new(move |buffer| {
|
||||
processed_audio_
|
||||
.lock()
|
||||
.unwrap()
|
||||
.extend_from_slice((*buffer).as_ref());
|
||||
let _ = sender.lock().unwrap().send(());
|
||||
}));
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let canceller = window.task_canceller(TaskSourceName::DOMManipulation);
|
||||
Builder::new()
|
||||
.name("OfflineAudioContextResolver".to_owned())
|
||||
.spawn(move || {
|
||||
let _ = receiver.recv();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(resolve: move || {
|
||||
let this = this.root();
|
||||
let processed_audio = processed_audio.lock().unwrap();
|
||||
let buffer = AudioBuffer::new(
|
||||
&this.global().as_window(),
|
||||
this.channel_count,
|
||||
this.length,
|
||||
*this.context.SampleRate(),
|
||||
Some(processed_audio.as_slice()));
|
||||
(*this.pending_rendering_promise.borrow_mut()).take().unwrap().resolve_native(&buffer);
|
||||
let global = &this.global();
|
||||
let window = global.as_window();
|
||||
let event = OfflineAudioCompletionEvent::new(&window,
|
||||
atom!("complete"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
&buffer);
|
||||
event.upcast::<Event>().fire(this.upcast());
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
if self.context.audio_context_impl().resume().is_err() {
|
||||
promise.reject_error(Error::Type("Could not start offline rendering".to_owned()));
|
||||
}
|
||||
|
||||
promise
|
||||
}
|
||||
}
|
132
components/script/dom/oscillatornode.rs
Normal file
132
components/script/dom/oscillatornode.rs
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::audioparam::AudioParam;
|
||||
use dom::audioscheduledsourcenode::AudioScheduledSourceNode;
|
||||
use dom::baseaudiocontext::BaseAudioContext;
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||
use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
|
||||
use dom::bindings::codegen::Bindings::OscillatorNodeBinding::{self, OscillatorOptions, OscillatorType};
|
||||
use dom::bindings::codegen::Bindings::OscillatorNodeBinding::OscillatorNodeMethods;
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_media::audio::node::AudioNodeInit;
|
||||
use servo_media::audio::oscillator_node::OscillatorNodeOptions as ServoMediaOscillatorOptions;
|
||||
use servo_media::audio::oscillator_node::OscillatorType as ServoMediaOscillatorType;
|
||||
use servo_media::audio::param::ParamType;
|
||||
use std::f32;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OscillatorNode {
|
||||
source_node: AudioScheduledSourceNode,
|
||||
oscillator_type: OscillatorType,
|
||||
frequency: Dom<AudioParam>,
|
||||
detune: Dom<AudioParam>,
|
||||
}
|
||||
|
||||
impl OscillatorNode {
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new_inherited(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
oscillator_options: &OscillatorOptions,
|
||||
) -> OscillatorNode {
|
||||
let mut node_options = AudioNodeOptions::empty();
|
||||
node_options.channelCount = Some(2);
|
||||
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
||||
node_options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
||||
let source_node = AudioScheduledSourceNode::new_inherited(
|
||||
AudioNodeInit::OscillatorNode(oscillator_options.into()),
|
||||
context,
|
||||
&node_options,
|
||||
0, /* inputs */
|
||||
1, /* outputs */
|
||||
);
|
||||
let node_id = source_node.node().node_id();
|
||||
let frequency = AudioParam::new(
|
||||
window,
|
||||
context,
|
||||
node_id,
|
||||
ParamType::Frequency,
|
||||
AutomationRate::A_rate,
|
||||
440.,
|
||||
f32::MIN,
|
||||
f32::MAX,
|
||||
);
|
||||
let detune = AudioParam::new(
|
||||
window,
|
||||
context,
|
||||
node_id,
|
||||
ParamType::Detune,
|
||||
AutomationRate::A_rate,
|
||||
0.,
|
||||
-440. / 2.,
|
||||
440. / 2.,
|
||||
);
|
||||
|
||||
OscillatorNode {
|
||||
source_node,
|
||||
oscillator_type: oscillator_options.type_,
|
||||
frequency: Dom::from_ref(&frequency),
|
||||
detune: Dom::from_ref(&detune),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &OscillatorOptions,
|
||||
) -> DomRoot<OscillatorNode> {
|
||||
let node = OscillatorNode::new_inherited(window, context, options);
|
||||
reflect_dom_object(Box::new(node), window, OscillatorNodeBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(
|
||||
window: &Window,
|
||||
context: &BaseAudioContext,
|
||||
options: &OscillatorOptions,
|
||||
) -> Fallible<DomRoot<OscillatorNode>> {
|
||||
Ok(OscillatorNode::new(window, context, options))
|
||||
}
|
||||
}
|
||||
|
||||
impl OscillatorNodeMethods for OscillatorNode {
|
||||
// https://webaudio.github.io/web-audio-api/#dom-oscillatornode-frequency
|
||||
fn Frequency(&self) -> DomRoot<AudioParam> {
|
||||
DomRoot::from_ref(&self.frequency)
|
||||
}
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#dom-oscillatornode-detune
|
||||
fn Detune(&self) -> DomRoot<AudioParam> {
|
||||
DomRoot::from_ref(&self.detune)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a OscillatorOptions> for ServoMediaOscillatorOptions {
|
||||
fn from(options: &'a OscillatorOptions) -> Self {
|
||||
Self {
|
||||
oscillator_type: options.type_.into(),
|
||||
freq: *options.frequency,
|
||||
detune: *options.detune,
|
||||
periodic_wave_options: None, // XXX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OscillatorType> for ServoMediaOscillatorType {
|
||||
fn from(oscillator_type: OscillatorType) -> Self {
|
||||
match oscillator_type {
|
||||
OscillatorType::Sine => ServoMediaOscillatorType::Sine,
|
||||
OscillatorType::Square => ServoMediaOscillatorType::Square,
|
||||
OscillatorType::Sawtooth => ServoMediaOscillatorType::Sawtooth,
|
||||
OscillatorType::Triangle => ServoMediaOscillatorType::Triangle,
|
||||
OscillatorType::Custom => ServoMediaOscillatorType::Custom,
|
||||
}
|
||||
}
|
||||
}
|
29
components/script/dom/webidls/AudioBuffer.webidl
Normal file
29
components/script/dom/webidls/AudioBuffer.webidl
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#audiobuffer
|
||||
*/
|
||||
|
||||
dictionary AudioBufferOptions {
|
||||
unsigned long numberOfChannels = 1;
|
||||
required unsigned long length;
|
||||
required float sampleRate;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor (AudioBufferOptions options)]
|
||||
interface AudioBuffer {
|
||||
readonly attribute float sampleRate;
|
||||
readonly attribute unsigned long length;
|
||||
readonly attribute double duration;
|
||||
readonly attribute unsigned long numberOfChannels;
|
||||
[Throws] Float32Array getChannelData(unsigned long channel);
|
||||
[Throws] void copyFromChannel(Float32Array destination,
|
||||
unsigned long channelNumber,
|
||||
optional unsigned long startInChannel = 0);
|
||||
[Throws] void copyToChannel(Float32Array source,
|
||||
unsigned long channelNumber,
|
||||
optional unsigned long startInChannel = 0);
|
||||
};
|
30
components/script/dom/webidls/AudioBufferSourceNode.webidl
Normal file
30
components/script/dom/webidls/AudioBufferSourceNode.webidl
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#AudioBufferSourceNode
|
||||
*/
|
||||
|
||||
dictionary AudioBufferSourceOptions {
|
||||
// AudioBuffer? buffer;
|
||||
float detune = 0;
|
||||
boolean loop = false;
|
||||
double loopEnd = 0;
|
||||
double loopStart = 0;
|
||||
float playbackRate = 1;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor (BaseAudioContext context, optional AudioBufferSourceOptions options)]
|
||||
interface AudioBufferSourceNode : AudioScheduledSourceNode {
|
||||
[Throws] attribute AudioBuffer? buffer;
|
||||
readonly attribute AudioParam playbackRate;
|
||||
readonly attribute AudioParam detune;
|
||||
attribute boolean loop;
|
||||
attribute double loopStart;
|
||||
attribute double loopEnd;
|
||||
[Throws] void start(optional double when = 0,
|
||||
optional double offset,
|
||||
optional double duration);
|
||||
};
|
40
components/script/dom/webidls/AudioContext.webidl
Normal file
40
components/script/dom/webidls/AudioContext.webidl
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#dom-audiocontext
|
||||
*/
|
||||
|
||||
enum AudioContextLatencyCategory {
|
||||
"balanced",
|
||||
"interactive",
|
||||
"playback"
|
||||
};
|
||||
|
||||
dictionary AudioContextOptions {
|
||||
AudioContextLatencyCategory latencyHint = "interactive";
|
||||
float sampleRate;
|
||||
};
|
||||
|
||||
dictionary AudioTimestamp {
|
||||
double contextTime;
|
||||
DOMHighResTimeStamp performanceTime;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor(optional AudioContextOptions contextOptions)]
|
||||
interface AudioContext : BaseAudioContext {
|
||||
readonly attribute double baseLatency;
|
||||
readonly attribute double outputLatency;
|
||||
|
||||
AudioTimestamp getOutputTimestamp();
|
||||
|
||||
Promise<void> suspend();
|
||||
Promise<void> close();
|
||||
|
||||
// MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
|
||||
// MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
|
||||
// MediaStreamTrackAudioSourceNode createMediaStreamTrackSource(MediaStreamTrack mediaStreamTrack);
|
||||
// MediaStreamAudioDestinationNode createMediaStreamDestination();
|
||||
};
|
12
components/script/dom/webidls/AudioDestinationNode.webidl
Normal file
12
components/script/dom/webidls/AudioDestinationNode.webidl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#dom-audiodestinationnode
|
||||
*/
|
||||
|
||||
[Exposed=Window]
|
||||
interface AudioDestinationNode : AudioNode {
|
||||
readonly attribute unsigned long maxChannelCount;
|
||||
};
|
61
components/script/dom/webidls/AudioNode.webidl
Normal file
61
components/script/dom/webidls/AudioNode.webidl
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#dom-audionode
|
||||
*/
|
||||
|
||||
enum ChannelCountMode {
|
||||
"max",
|
||||
"clamped-max",
|
||||
"explicit"
|
||||
};
|
||||
|
||||
enum ChannelInterpretation {
|
||||
"speakers",
|
||||
"discrete"
|
||||
};
|
||||
|
||||
dictionary AudioNodeOptions {
|
||||
unsigned long channelCount;
|
||||
ChannelCountMode channelCountMode;
|
||||
ChannelInterpretation channelInterpretation;
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface AudioNode : EventTarget {
|
||||
[Throws]
|
||||
AudioNode connect(AudioNode destinationNode,
|
||||
optional unsigned long output = 0,
|
||||
optional unsigned long input = 0);
|
||||
[Throws]
|
||||
void connect(AudioParam destinationParam,
|
||||
optional unsigned long output = 0);
|
||||
[Throws]
|
||||
void disconnect();
|
||||
[Throws]
|
||||
void disconnect(unsigned long output);
|
||||
[Throws]
|
||||
void disconnect(AudioNode destination);
|
||||
[Throws]
|
||||
void disconnect(AudioNode destination, unsigned long output);
|
||||
[Throws]
|
||||
void disconnect(AudioNode destination,
|
||||
unsigned long output,
|
||||
unsigned long input);
|
||||
[Throws]
|
||||
void disconnect(AudioParam destination);
|
||||
[Throws]
|
||||
void disconnect(AudioParam destination, unsigned long output);
|
||||
|
||||
readonly attribute BaseAudioContext context;
|
||||
readonly attribute unsigned long numberOfInputs;
|
||||
readonly attribute unsigned long numberOfOutputs;
|
||||
|
||||
[SetterThrows]
|
||||
attribute unsigned long channelCount;
|
||||
[SetterThrows]
|
||||
attribute ChannelCountMode channelCountMode;
|
||||
attribute ChannelInterpretation channelInterpretation;
|
||||
};
|
32
components/script/dom/webidls/AudioParam.webidl
Normal file
32
components/script/dom/webidls/AudioParam.webidl
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#dom-audioparam
|
||||
*/
|
||||
|
||||
enum AutomationRate {
|
||||
"a-rate",
|
||||
"k-rate"
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface AudioParam {
|
||||
attribute float value;
|
||||
attribute AutomationRate automationRate;
|
||||
readonly attribute float defaultValue;
|
||||
readonly attribute float minValue;
|
||||
readonly attribute float maxValue;
|
||||
AudioParam setValueAtTime(float value, double startTime);
|
||||
AudioParam linearRampToValueAtTime(float value, double endTime);
|
||||
AudioParam exponentialRampToValueAtTime(float value, double endTime);
|
||||
AudioParam setTargetAtTime(float target,
|
||||
double startTime,
|
||||
float timeConstant);
|
||||
// AudioParam setValueCurveAtTime(sequence<float> values,
|
||||
// double startTime,
|
||||
// double duration);
|
||||
AudioParam cancelScheduledValues(double cancelTime);
|
||||
AudioParam cancelAndHoldAtTime(double cancelTime);
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#AudioScheduledSourceNode
|
||||
*/
|
||||
|
||||
[Exposed=Window]
|
||||
interface AudioScheduledSourceNode : AudioNode {
|
||||
attribute EventHandler onended;
|
||||
[Throws] void start(optional double when = 0);
|
||||
[Throws] void stop(optional double when = 0);
|
||||
};
|
55
components/script/dom/webidls/BaseAudioContext.webidl
Normal file
55
components/script/dom/webidls/BaseAudioContext.webidl
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#BaseAudioContext
|
||||
*/
|
||||
|
||||
enum AudioContextState {
|
||||
"suspended",
|
||||
"running",
|
||||
"closed"
|
||||
};
|
||||
|
||||
callback DecodeErrorCallback = void (DOMException error);
|
||||
callback DecodeSuccessCallback = void (AudioBuffer decodedData);
|
||||
|
||||
[Exposed=Window]
|
||||
interface BaseAudioContext : EventTarget {
|
||||
readonly attribute AudioDestinationNode destination;
|
||||
readonly attribute float sampleRate;
|
||||
readonly attribute double currentTime;
|
||||
// readonly attribute AudioListener listener;
|
||||
readonly attribute AudioContextState state;
|
||||
Promise<void> resume();
|
||||
attribute EventHandler onstatechange;
|
||||
[Throws] AudioBuffer createBuffer(unsigned long numberOfChannels,
|
||||
unsigned long length,
|
||||
float sampleRate);
|
||||
Promise<AudioBuffer> decodeAudioData(ArrayBuffer audioData,
|
||||
optional DecodeSuccessCallback successCallback,
|
||||
optional DecodeErrorCallback errorCallback);
|
||||
AudioBufferSourceNode createBufferSource();
|
||||
// ConstantSourceNode createConstantSource();
|
||||
// ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
|
||||
// optional unsigned long numberOfInputChannels = 2,
|
||||
// optional unsigned long numberOfOutputChannels = 2);
|
||||
// AnalyserNode createAnalyser();
|
||||
GainNode createGain();
|
||||
// DelayNode createDelay(optional double maxDelayTime = 1);
|
||||
// BiquadFilterNode createBiquadFilter();
|
||||
// IIRFilterNode createIIRFilter(sequence<double> feedforward,
|
||||
// sequence<double> feedback);
|
||||
// WaveShaperNode createWaveShaper();
|
||||
// PannerNode createPanner();
|
||||
// StereoPannerNode createStereoPanner();
|
||||
// ConvolverNode createConvolver();
|
||||
// ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
|
||||
// ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
|
||||
// DynamicsCompressorNode createDynamicsCompressor();
|
||||
OscillatorNode createOscillator();
|
||||
// PeriodicWave createPeriodicWave(sequence<float> real,
|
||||
// sequence<float> imag,
|
||||
// optional PeriodicWaveConstraints constraints);
|
||||
};
|
17
components/script/dom/webidls/GainNode.webidl
Normal file
17
components/script/dom/webidls/GainNode.webidl
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#gainnode
|
||||
*/
|
||||
|
||||
dictionary GainOptions : AudioNodeOptions {
|
||||
float gain = 1.0;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor (BaseAudioContext context, optional GainOptions options)]
|
||||
interface GainNode : AudioNode {
|
||||
readonly attribute AudioParam gain;
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* For more information on this interface please see
|
||||
* https://webaudio.github.io/web-audio-api/#offlineaudiocompletionevent
|
||||
*/
|
||||
|
||||
dictionary OfflineAudioCompletionEventInit : EventInit {
|
||||
required AudioBuffer renderedBuffer;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor(DOMString type, OfflineAudioCompletionEventInit eventInitDict)]
|
||||
interface OfflineAudioCompletionEvent : Event {
|
||||
readonly attribute AudioBuffer renderedBuffer;
|
||||
};
|
24
components/script/dom/webidls/OfflineAudioContext.webidl
Normal file
24
components/script/dom/webidls/OfflineAudioContext.webidl
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#OfflineAudioContext
|
||||
*/
|
||||
|
||||
dictionary OfflineAudioContextOptions {
|
||||
unsigned long numberOfChannels = 1;
|
||||
required unsigned long length;
|
||||
required float sampleRate;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor (OfflineAudioContextOptions contextOptions),
|
||||
Constructor (unsigned long numberOfChannels, unsigned long length, float sampleRate)]
|
||||
interface OfflineAudioContext : BaseAudioContext {
|
||||
readonly attribute unsigned long length;
|
||||
attribute EventHandler oncomplete;
|
||||
|
||||
Promise<AudioBuffer> startRendering();
|
||||
// Promise<void> suspend(double suspendTime);
|
||||
};
|
34
components/script/dom/webidls/OscillatorNode.webidl
Normal file
34
components/script/dom/webidls/OscillatorNode.webidl
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://webaudio.github.io/web-audio-api/#oscillatornode
|
||||
*/
|
||||
|
||||
enum OscillatorType {
|
||||
"sine",
|
||||
"square",
|
||||
"sawtooth",
|
||||
"triangle",
|
||||
"custom"
|
||||
};
|
||||
|
||||
dictionary OscillatorOptions : AudioNodeOptions {
|
||||
OscillatorType type = "sine";
|
||||
float frequency = 440;
|
||||
float detune = 0;
|
||||
// PeriodicWave periodicWave;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor (BaseAudioContext context, optional OscillatorOptions options)]
|
||||
interface OscillatorNode : AudioScheduledSourceNode {
|
||||
// [SetterThrows]
|
||||
// attribute OscillatorType type;
|
||||
|
||||
readonly attribute AudioParam frequency;
|
||||
readonly attribute AudioParam detune;
|
||||
|
||||
// void setPeriodicWave (PeriodicWave periodicWave);
|
||||
};
|
|
@ -86,6 +86,7 @@ extern crate servo_arc;
|
|||
#[macro_use] extern crate servo_atoms;
|
||||
extern crate servo_config;
|
||||
extern crate servo_geometry;
|
||||
extern crate servo_media;
|
||||
extern crate servo_rand;
|
||||
extern crate servo_url;
|
||||
extern crate smallvec;
|
||||
|
|
|
@ -28,7 +28,7 @@ fnv = "1.0"
|
|||
phf = "0.7.18"
|
||||
precomputed-hash = "0.1"
|
||||
servo_arc = { version = "0.1", path = "../servo_arc" }
|
||||
smallvec = "0.6"
|
||||
smallvec = "0.6.2"
|
||||
|
||||
[build-dependencies]
|
||||
phf_codegen = "0.7.18"
|
||||
|
|
|
@ -60,7 +60,7 @@ servo_arc = { path = "../servo_arc" }
|
|||
servo_atoms = {path = "../atoms", optional = true}
|
||||
servo_config = {path = "../config", optional = true}
|
||||
smallbitvec = "2.1.1"
|
||||
smallvec = "0.6"
|
||||
smallvec = "0.6.2"
|
||||
string_cache = { version = "0.7", optional = true }
|
||||
style_derive = {path = "../style_derive"}
|
||||
style_traits = {path = "../style_traits"}
|
||||
|
|
|
@ -94,6 +94,7 @@ WEBIDL_STANDARDS = [
|
|||
"//webbluetoothcg.github.io/web-bluetooth/",
|
||||
"//svgwg.org/svg2-draft",
|
||||
"//wicg.github.io",
|
||||
"//webaudio.github.io",
|
||||
# Not a URL
|
||||
"// This interface is entirely internal to Servo, and should not be" +
|
||||
" accessible to\n// web pages."
|
||||
|
|
|
@ -107,6 +107,8 @@ skip: true
|
|||
skip: false
|
||||
[url]
|
||||
skip: false
|
||||
[webaudio]
|
||||
skip: false
|
||||
[WebCryptoAPI]
|
||||
skip: false
|
||||
[webgl]
|
||||
|
|
13
tests/wpt/metadata/webaudio/historical.html.ini
Normal file
13
tests/wpt/metadata/webaudio/historical.html.ini
Normal file
|
@ -0,0 +1,13 @@
|
|||
[historical.html]
|
||||
[dopplerFactor member should not exist on the AudioListener.]
|
||||
expected: FAIL
|
||||
|
||||
[speedOfSound member should not exist on the AudioListener.]
|
||||
expected: FAIL
|
||||
|
||||
[setVelocity member should not exist on the AudioListener.]
|
||||
expected: FAIL
|
||||
|
||||
[setVelocity should not exist on PannerNodes.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[idlharness.https.window.html]
|
||||
[idlharness]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[ctor-analyser.html]
|
||||
expected: ERROR
|
||||
[X context = new OfflineAudioContext(...) incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
||||
expected: FAIL
|
||||
|
||||
[< [initialize\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X node0 = new AnalyserNode(context) incorrectly threw TypeError: "window[name\] is not a constructor".]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[realtimeanalyser-basic.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[realtimeanalyser-fft-scaling.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[realtimeanalyser-fft-sizing.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,4 @@
|
|||
[test-analyser-gain.html]
|
||||
[Test effect of AnalyserNode on GainNode output]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[test-analyser-minimum.html]
|
||||
[Test AnalyserNode when the input is silent]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[test-analyser-output.html]
|
||||
[AnalyserNode output]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[test-analyser-scale.html]
|
||||
[Test AnalyserNode when the input is scaled]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[test-analysernode.html]
|
||||
[Test AnalyserNode API]
|
||||
expected: FAIL
|
||||
|
||||
[Test AnalyserNode's ctor API]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audiobuffer-copy-channel.html]
|
||||
expected: CRASH
|
|
@ -0,0 +1,8 @@
|
|||
[ctor-audiobuffer.html]
|
||||
expected: CRASH
|
||||
[X context = new OfflineAudioContext(...) incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
||||
expected: FAIL
|
||||
|
||||
[< [initialize\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
[audiobuffersource-basic.html]
|
||||
[X start(-1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X start(0,-1) threw "InvalidStateError" instead of function RangeError() {\n [native code\]\n}.]
|
||||
expected: FAIL
|
||||
|
||||
[X start(0,0,-1) threw "InvalidStateError" instead of function RangeError() {\n [native code\]\n}.]
|
||||
expected: FAIL
|
||||
|
||||
[X stop(-1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[< [start/stop exceptions\] 1 out of 12 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[audiobuffersource-channels.html]
|
||||
[X source.buffer = buffer again did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[< [validate .buffer\] 1 out of 16 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audiobuffersource-ended.html]
|
||||
expected: TIMEOUT
|
|
@ -0,0 +1,2 @@
|
|||
[audiobuffersource-multi-channels.html]
|
||||
expected: TIMEOUT
|
|
@ -0,0 +1,10 @@
|
|||
[audiobuffersource-one-sample-loop.html]
|
||||
[X Rendered data: Expected 1 for all values but found 998 unexpected values: \n\tIndex\tActual\n\t[1\]\t0\n\t[2\]\t0\n\t[3\]\t0\n\t[4\]\t0\n\t...and 994 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[< [one-sample-loop\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audiobuffersource-playbackrate-zero.html]
|
||||
expected: CRASH
|
|
@ -0,0 +1,28 @@
|
|||
[audiobuffersource-start.html]
|
||||
[X Case 0: start(when): implicitly play whole buffer from beginning to end expected to be equal to the array [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0...\] but differs in 7 places:\n\tIndex\tActual\t\t\tExpected\n\t[1\]\t9.0000000000000000e+0\t1.0000000000000000e+0\n\t[2\]\t1.8000000000000000e+1\t2.0000000000000000e+0\n\t[3\]\t2.7000000000000000e+1\t3.0000000000000000e+0\n\t[4\]\t3.6000000000000000e+1\t4.0000000000000000e+0\n\t...and 3 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[X Case 1: start(when, 0): play whole buffer from beginning to end explicitly giving offset of 0 expected to be equal to the array [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0...\] but differs in 7 places:\n\tIndex\tActual\t\t\tExpected\n\t[1\]\t0.0000000000000000e+0\t1.0000000000000000e+0\n\t[2\]\t0.0000000000000000e+0\t2.0000000000000000e+0\n\t[3\]\t0.0000000000000000e+0\t3.0000000000000000e+0\n\t[4\]\t0.0000000000000000e+0\t4.0000000000000000e+0\n\t...and 3 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[X Case 2: start(when, 0, 8_frames): play whole buffer from beginning to end explicitly giving offset of 0 and duration of 8 frames expected to be equal to the array [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0...\] but differs in 7 places:\n\tIndex\tActual\t\t\tExpected\n\t[1\]\t0.0000000000000000e+0\t1.0000000000000000e+0\n\t[2\]\t0.0000000000000000e+0\t2.0000000000000000e+0\n\t[3\]\t0.0000000000000000e+0\t3.0000000000000000e+0\n\t[4\]\t0.0000000000000000e+0\t4.0000000000000000e+0\n\t...and 3 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[X Case 3: start(when, 4_frames): play with explicit non-zero offset expected to be equal to the array [4,5,6,7,0,0,0,0,0,0,0,0,0,0,0,0...\] but differs in 4 places:\n\tIndex\tActual\t\t\tExpected\n\t[0\]\t0.0000000000000000e+0\t4.0000000000000000e+0\n\t[1\]\t0.0000000000000000e+0\t5.0000000000000000e+0\n\t[2\]\t0.0000000000000000e+0\t6.0000000000000000e+0\n\t[3\]\t0.0000000000000000e+0\t7.0000000000000000e+0\n\t...and 0 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[X Case 4: start(when, 4_frames, 4_frames): play with explicit non-zero offset and duration expected to be equal to the array [4,5,6,7,0,0,0,0,0,0,0,0,0,0,0,0...\] but differs in 4 places:\n\tIndex\tActual\t\t\tExpected\n\t[0\]\t0.0000000000000000e+0\t4.0000000000000000e+0\n\t[1\]\t0.0000000000000000e+0\t5.0000000000000000e+0\n\t[2\]\t0.0000000000000000e+0\t6.0000000000000000e+0\n\t[3\]\t0.0000000000000000e+0\t7.0000000000000000e+0\n\t...and 0 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[X Case 5: start(when, 7_frames): play with explicit non-zero offset near end of buffer expected to be equal to the array [7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...\] but differs in 1 places:\n\tIndex\tActual\t\t\tExpected\n\t[0\]\t0.0000000000000000e+0\t7.0000000000000000e+0]
|
||||
expected: FAIL
|
||||
|
||||
[X Case 8: start(when, 0, 15_frames): play with whole buffer, with long duration (clipped) expected to be equal to the array [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0...\] but differs in 7 places:\n\tIndex\tActual\t\t\tExpected\n\t[1\]\t0.0000000000000000e+0\t1.0000000000000000e+0\n\t[2\]\t0.0000000000000000e+0\t2.0000000000000000e+0\n\t[3\]\t0.0000000000000000e+0\t3.0000000000000000e+0\n\t[4\]\t0.0000000000000000e+0\t4.0000000000000000e+0\n\t...and 3 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[< [Tests AudioBufferSourceNode start()\] 7 out of 18 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[audiosource-time-limits.html]
|
||||
[X Output from AudioBufferSource.stop(1e+300): Expected 1 for all values but found 999 unexpected values: \n\tIndex\tActual\n\t[0\]\t0\n\t[1\]\t0\n\t[2\]\t0\n\t[3\]\t0\n\t...and 995 more errors.]
|
||||
expected: FAIL
|
||||
|
||||
[< [buffersource: huge stop time\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X Peak amplitude from oscillator.stop(1e+300) is not greater than 0. Got 0.]
|
||||
expected: FAIL
|
||||
|
||||
[< [oscillator: huge stop time\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 2 out of 2 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
[ctor-audiobuffersource.html]
|
||||
[X context = new OfflineAudioContext(...) incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
||||
expected: FAIL
|
||||
|
||||
[< [initialize\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X node0 = new AudioBufferSourceNode(context) incorrectly threw TypeError: "Value is not an object.".]
|
||||
expected: FAIL
|
||||
|
||||
[X node0 instanceof AudioBufferSourceNode is not equal to true. Got false.]
|
||||
expected: FAIL
|
||||
|
||||
[X node2.buffer === buffer is not equal to true. Got false.]
|
||||
expected: FAIL
|
||||
|
||||
[< [constructor options\] 1 out of 7 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 5 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[note-grain-on-play.html]
|
||||
expected: CRASH
|
|
@ -0,0 +1,22 @@
|
|||
[note-grain-on-timing.html]
|
||||
[X Number of start frames is not equal to 100. Got 1.]
|
||||
expected: FAIL
|
||||
|
||||
[X Number of end frames is not equal to 100. Got 1.]
|
||||
expected: FAIL
|
||||
|
||||
[X Pulse 0 boundary expected to be equal to the array [0,441\] but differs in 1 places:\n\tIndex\tActual\t\t\tExpected\n\t[1\]\t4.8520000000000000e+3\t4.4100000000000000e+2]
|
||||
expected: FAIL
|
||||
|
||||
[X Number of grains that started at the correct time is not equal to 100. Got 1.]
|
||||
expected: FAIL
|
||||
|
||||
[X Number of grains out of 100 that ended at the wrong time is not equal to 0. Got 1.]
|
||||
expected: FAIL
|
||||
|
||||
[< [Test timing of noteGrainOn\] 5 out of 6 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[sample-accurate-scheduling.html]
|
||||
[X Non-zero sample found at sample offset 176399 is not true. Got false.]
|
||||
expected: FAIL
|
||||
|
||||
[X Number of impulses found is not equal to 9. Got 2.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test\] 2 out of 4 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[audiocontext-suspend-resume.html]
|
||||
expected: ERROR
|
||||
[X offlineContext = new OfflineAudioContext(1, 44100, 44100) incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
||||
expected: FAIL
|
||||
|
||||
[X p1 = offlineContext.suspend() incorrectly threw TypeError: "offlineContext.suspend is not a function".]
|
||||
expected: FAIL
|
||||
|
||||
[X p1 instanceof Promise is not true. Got false.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
[audiocontextoptions.html]
|
||||
expected: TIMEOUT
|
||||
[X default baseLatency is not greater than 0. Got 0.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test-audiocontextoptions-latencyHint-basic\] 1 out of 9 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X context = new AudioContext({'latencyHint': interactiveLatency/2}) incorrectly threw TypeError: "'0' is not a valid enum value for enumeration 'AudioContextLatencyCategory'.".]
|
||||
expected: FAIL
|
||||
|
||||
[X context = new AudioContext({'latencyHint': validLatency}) incorrectly threw TypeError: "'0' is not a valid enum value for enumeration 'AudioContextLatencyCategory'.".]
|
||||
expected: FAIL
|
||||
|
||||
[X creating two high latency contexts incorrectly threw TypeError: "'0' is not a valid enum value for enumeration 'AudioContextLatencyCategory'.".]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audionode-channel-rules.html]
|
||||
expected: CRASH
|
|
@ -0,0 +1,2 @@
|
|||
[audionode-connect-method-chaining.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[audionode-connect-order.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[audionode-disconnect-audioparam.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[audionode-disconnect.html]
|
||||
expected: TIMEOUT
|
|
@ -0,0 +1,16 @@
|
|||
[audionode.html]
|
||||
[X AudioContext.destination.numberOfOutputs is not equal to 0. Got 1.]
|
||||
expected: FAIL
|
||||
|
||||
[X Connecting a node to a different context did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test\] 2 out of 12 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test\] 1 out of 12 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audioparam-connect-audioratesignal.html]
|
||||
expected: CRASH
|
|
@ -0,0 +1,49 @@
|
|||
[audioparam-exceptional-values.html]
|
||||
[X Creating context for testing incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
||||
expected: FAIL
|
||||
|
||||
[< [initialize\] 1 out of 1 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.setValueAtTime(1,-1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.linearRampToValueAtTime(1,-1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.exponentialRampToValueAtTime(1,-1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.setTargetAtTime(1,-1,1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.setTargetAtTime(1,1,-1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.setValueCurveAtTime([[object Float32Array\]\],-1,1) threw "TypeError" instead of function RangeError() {\n [native code\]\n}.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.setValueCurveAtTime([[object Float32Array\]\],1,-1) threw "TypeError" instead of function RangeError() {\n [native code\]\n}.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.setValueCurveAtTime(curve, 1, 0) threw "TypeError" instead of function RangeError() {\n [native code\]\n}.]
|
||||
expected: FAIL
|
||||
|
||||
[< [special cases 1\] 8 out of 8 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.exponentialRampToValueAtTime(0,1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.exponentialRampToValueAtTime(-1e-100,1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X gain.gain.exponentialRampToValueAtTime(1e-100,1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[< [special cases 2\] 3 out of 3 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 2 out of 6 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
[audioparam-exponentialRampToValueAtTime.html]
|
||||
[X Max error for test 0 at offset 1322 is not less than or equal to 0.00001222. Got 0.004971347529273832.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 1 at offset 2645 is not less than or equal to 0.00001222. Got 0.00507232754748583.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 2 at offset 3968 is not less than or equal to 0.00001222. Got 0.005072288986783049.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 3 at offset 5291 is not less than or equal to 0.00001222. Got 0.005177453099763553.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 4 at offset 6614 is not less than or equal to 0.00001222. Got 0.005177414562697979.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 5 at offset 7937 is not less than or equal to 0.00001222. Got 0.005287028393264749.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 6 at offset 9260 is not less than or equal to 0.00001222. Got 0.005286989916402489.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 7 at offset 10583 is not less than or equal to 0.00001222. Got 0.005401342058686055.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 8 at offset 11906 is not less than or equal to 0.00001222. Got 0.00540130368332191.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 9 at offset 13229 is not less than or equal to 0.00001222. Got 0.005520708240934441.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 10 at offset 14552 is not less than or equal to 0.00001222. Got 0.005520670013722852.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 11 at offset 15875 is not less than or equal to 0.00001222. Got 0.005645469482076645.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 12 at offset 17198 is not less than or equal to 0.00001222. Got 0.005645431455758545.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 13 at offset 18521 is not less than or equal to 0.00001222. Got 0.005776000004233634.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 14 at offset 19844 is not less than or equal to 0.00001222. Got 0.0057759622384759915.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 15 at offset 21167 is not less than or equal to 0.00001222. Got 0.0059127094586828586.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 16 at offset 22490 is not less than or equal to 0.00001222. Got 0.005912672021051084.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 17 at offset 23813 is not less than or equal to 0.00001222. Got 0.006056047220282001.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 18 at offset 25136 is not less than or equal to 0.00001222. Got 0.006056010187369548.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 19 at offset 26459 is not less than or equal to 0.00001222. Got 0.006206507322052307.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 20 at offset 27782 is not less than or equal to 0.00001222. Got 0.006206470780796884.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 21 at offset 29105 is not less than or equal to 0.00001222. Got 0.0063646341440895165.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 22 at offset 30428 is not less than or equal to 0.00001222. Got 0.00636459819331172.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 23 at offset 31751 is not less than or equal to 0.00001222. Got 0.006531028994848638.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 24 at offset 33074 is not less than or equal to 0.00001222. Got 0.0065309937470566844.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 25 at offset 34397 is not less than or equal to 0.00001222. Got 0.006706357752496105.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 26 at offset 35720 is not less than or equal to 0.00001222. Got 0.006706323336010292.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 27 at offset 37043 is not less than or equal to 0.00001222. Got 0.006891359771030949.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 28 at offset 38366 is not less than or equal to 0.00001222. Got 0.00689132633249392.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 29 at offset 39689 is not less than or equal to 0.00001222. Got 0.007086858302333446.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 30 at offset 41012 is not less than or equal to 0.00001222. Got 0.007086826009688193.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 31 at offset 42335 is not less than or equal to 0.00001222. Got 0.007293772743964152.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 32 at offset 43658 is not less than or equal to 0.00001222. Got 0.0072937417900018064.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 33 at offset 44981 is not less than or equal to 0.00001222. Got 0.007513133097079656.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 34 at offset 46304 is not less than or equal to 0.00001222. Got 0.007513103703685007.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 35 at offset 47627 is not less than or equal to 0.00001222. Got 0.0077460971141775446.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 36 at offset 48950 is not less than or equal to 0.00001222. Got 0.00774606953743358.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 37 at offset 50273 is not less than or equal to 0.00001222. Got 0.00799390921649094.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 38 at offset 51596 is not less than or equal to 0.00001222. Got 0.007993945275544895.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 39 at offset 52919 is not less than or equal to 0.00001222. Got 0.008258169028622094.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 40 at offset 54242 is not less than or equal to 0.00001222. Got 0.008258272128077778.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 41 at offset 55565 is not less than or equal to 0.00001222. Got 0.008540497771090037.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 42 at offset 56888 is not less than or equal to 0.00001222. Got 0.008540543388584421.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 43 at offset 58211 is not less than or equal to 0.00001222. Got 0.008842814255529671.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 44 at offset 59534 is not less than or equal to 0.00001222. Got 0.008842932469887153.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 45 at offset 60857 is not less than or equal to 0.00001222. Got 0.009167318952047627.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 46 at offset 62180 is not less than or equal to 0.00001222. Got 0.009167376648625705.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 47 at offset 63503 is not less than or equal to 0.00001222. Got 0.009516547638069068.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 48 at offset 64826 is not less than or equal to 0.00001222. Got 0.009516684552275934.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 49 at offset 66149 is not less than or equal to 0.00001222. Got 0.009893514080660987.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 50 at offset 67472 is not less than or equal to 0.00001222. Got 0.009893510977195341.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 51 at offset 68795 is not less than or equal to 0.00001222. Got 0.010301411434863215.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 52 at offset 70118 is not less than or equal to 0.00001222. Got 0.010301571864146954.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 53 at offset 71441 is not less than or equal to 0.00001222. Got 0.010744562213274482.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 54 at offset 72764 is not less than or equal to 0.00001222. Got 0.010744572666723327.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 55 at offset 74087 is not less than or equal to 0.00001222. Got 0.01122737314374763.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 56 at offset 75410 is not less than or equal to 0.00001222. Got 0.011227478948691283.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 57 at offset 76733 is not less than or equal to 0.00001222. Got 0.01175580623231679.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 58 at offset 78056 is not less than or equal to 0.00001222. Got 0.011755835641619888.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 59 at offset 79379 is not less than or equal to 0.00001222. Got 0.012336239163652849.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 60 at offset 80702 is not less than or equal to 0.00001222. Got 0.012336376203148012.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 61 at offset 82025 is not less than or equal to 0.00001222. Got 0.012977176838334303.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 62 at offset 83348 is not less than or equal to 0.00001222. Got 0.01297723326480682.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 63 at offset 84671 is not less than or equal to 0.00001222. Got 0.013688247738325734.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 64 at offset 85994 is not less than or equal to 0.00001222. Got 0.013688321971339096.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 65 at offset 87317 is not less than or equal to 0.00001222. Got 0.014481760747876011.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 66 at offset 88640 is not less than or equal to 0.00001222. Got 0.014481856656908305.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 67 at offset 89963 is not less than or equal to 0.00001222. Got 0.01537293577367861.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 68 at offset 91286 is not less than or equal to 0.00001222. Got 0.015373058296300991.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 69 at offset 92609 is not less than or equal to 0.00001222. Got 0.016380921220530496.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 70 at offset 93932 is not less than or equal to 0.00001222. Got 0.016381078788684566.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 71 at offset 95255 is not less than or equal to 0.00001222. Got 0.01753058059001621.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 72 at offset 96578 is not less than or equal to 0.00001222. Got 0.01753077514543058.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 73 at offset 97901 is not less than or equal to 0.00001222. Got 0.018853551375474058.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 74 at offset 99224 is not less than or equal to 0.00001222. Got 0.018853800846327963.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 75 at offset 100547 is not less than or equal to 0.00001222. Got 0.020392593309963868.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 76 at offset 101870 is not less than or equal to 0.00001222. Got 0.02039291059393737.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 77 at offset 103193 is not less than or equal to 0.00001222. Got 0.022205238153527315.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 78 at offset 104516 is not less than or equal to 0.00001222. Got 0.022205561601247308.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 79 at offset 105839 is not less than or equal to 0.00001222. Got 0.024371468038865658.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 80 at offset 107162 is not less than or equal to 0.00001222. Got 0.024372089145737547.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 81 at offset 108485 is not less than or equal to 0.00001222. Got 0.0270063795920686.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 82 at offset 109808 is not less than or equal to 0.00001222. Got 0.027006863607415388.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 83 at offset 111131 is not less than or equal to 0.00001222. Got 0.030279806361083936.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 84 at offset 112454 is not less than or equal to 0.00001222. Got 0.030280498895388284.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 85 at offset 113777 is not less than or equal to 0.00001222. Got 0.03445622424898759.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 86 at offset 115100 is not less than or equal to 0.00001222. Got 0.03445703934642761.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 87 at offset 116423 is not less than or equal to 0.00001222. Got 0.03996905609650592.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 88 at offset 117746 is not less than or equal to 0.00001222. Got 0.03997048249087859.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 89 at offset 119069 is not less than or equal to 0.00001222. Got 0.04758232055157862.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 90 at offset 120392 is not less than or equal to 0.00001222. Got 0.047584013396256356.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 91 at offset 121715 is not less than or equal to 0.00001222. Got 0.05877779461906339.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 92 at offset 123038 is not less than or equal to 0.00001222. Got 0.05878033819291966.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 93 at offset 124361 is not less than or equal to 0.00001222. Got 0.07686264332095362.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 94 at offset 125684 is not less than or equal to 0.00001222. Got 0.07686707196371474.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 95 at offset 127007 is not less than or equal to 0.00001222. Got 0.1110222263568349.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 96 at offset 128330 is not less than or equal to 0.00001222. Got 0.11103236124822866.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 97 at offset 129653 is not less than or equal to 0.00001222. Got 0.19983522770615608.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 98 at offset 130976 is not less than or equal to 0.00001222. Got 0.19986539483609111.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 99 at offset 130979 is not less than or equal to 0.00001222. Got 0.0010478736613536294.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test\] 100 out of 102 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
[audioparam-linearRampToValueAtTime.html]
|
||||
[X Max error for test 0 at offset 1322 is not less than or equal to 0.000001865. Got 0.004971382585870938.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 1 at offset 2645 is not less than or equal to 0.000001865. Got 0.005072295510229919.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 2 at offset 3968 is not less than or equal to 0.000001865. Got 0.005072305387543696.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 3 at offset 5291 is not less than or equal to 0.000001865. Got 0.005177440159265024.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 4 at offset 6614 is not less than or equal to 0.000001865. Got 0.005177473300879752.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 5 at offset 7937 is not less than or equal to 0.000001865. Got 0.005286972284210275.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 6 at offset 9260 is not less than or equal to 0.000001865. Got 0.005287029709955556.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 7 at offset 10583 is not less than or equal to 0.000001865. Got 0.005401305351315997.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 8 at offset 11906 is not less than or equal to 0.000001865. Got 0.005401323712834355.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 9 at offset 13229 is not less than or equal to 0.000001865. Got 0.005520691792549967.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 10 at offset 14552 is not less than or equal to 0.000001865. Got 0.00552073526720557.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 11 at offset 15875 is not less than or equal to 0.000001865. Got 0.005645406858491471.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 12 at offset 17198 is not less than or equal to 0.000001865. Got 0.005645476626856955.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 13 at offset 18521 is not less than or equal to 0.000001865. Got 0.0057759579767177206.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 14 at offset 19844 is not less than or equal to 0.000001865. Got 0.005775986398284702.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 15 at offset 21167 is not less than or equal to 0.000001865. Got 0.005912689001894731.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 16 at offset 22490 is not less than or equal to 0.000001865. Got 0.005912744713046106.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 17 at offset 23813 is not less than or equal to 0.000001865. Got 0.006055977132018537.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 18 at offset 25136 is not less than or equal to 0.000001865. Got 0.006056061515967637.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 19 at offset 26459 is not less than or equal to 0.000001865. Got 0.00620645917849245.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 20 at offset 27782 is not less than or equal to 0.000001865. Got 0.0062064996841445265.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 21 at offset 29105 is not less than or equal to 0.000001865. Got 0.006364609063030028.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 22 at offset 30428 is not less than or equal to 0.000001865. Got 0.006364679458219021.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 23 at offset 31751 is not less than or equal to 0.000001865. Got 0.006530950267540621.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 24 at offset 33074 is not less than or equal to 0.000001865. Got 0.0065310521960605565.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 25 at offset 34397 is not less than or equal to 0.000001865. Got 0.006706302503957123.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 26 at offset 35720 is not less than or equal to 0.000001865. Got 0.006706357743664959.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 27 at offset 37043 is not less than or equal to 0.000001865. Got 0.0068913292960890915.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 28 at offset 38366 is not less than or equal to 0.000001865. Got 0.006891335371900766.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 29 at offset 39689 is not less than or equal to 0.000001865. Got 0.007086769460824398.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 30 at offset 41012 is not less than or equal to 0.000001865. Got 0.007086892787027758.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 31 at offset 42335 is not less than or equal to 0.000001865. Got 0.007293709140558525.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 32 at offset 43658 is not less than or equal to 0.000001865. Got 0.0072937826617006625.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 33 at offset 44981 is not less than or equal to 0.000001865. Got 0.007513096249085025.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 34 at offset 46304 is not less than or equal to 0.000001865. Got 0.007513117110837575.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 35 at offset 47627 is not less than or equal to 0.000001865. Got 0.007745996270211642.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 36 at offset 48950 is not less than or equal to 0.000001865. Got 0.007746146186898846.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 37 at offset 50273 is not less than or equal to 0.000001865. Got 0.007993897169413747.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 38 at offset 51596 is not less than or equal to 0.000001865. Got 0.007993993846002342.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 39 at offset 52919 is not less than or equal to 0.000001865. Got 0.008258188108327222.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 40 at offset 54242 is not less than or equal to 0.000001865. Got 0.008258228229559253.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 41 at offset 55565 is not less than or equal to 0.000001865. Got 0.008540448218182686.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 42 at offset 56888 is not less than or equal to 0.000001865. Got 0.00854063192705488.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 43 at offset 58211 is not less than or equal to 0.000001865. Got 0.00884279670524028.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 44 at offset 59534 is not less than or equal to 0.000001865. Got 0.008842923444757374.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 45 at offset 60857 is not less than or equal to 0.000001865. Got 0.009167335753064386.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 46 at offset 62180 is not less than or equal to 0.000001865. Got 0.009167401649722278.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 47 at offset 63503 is not less than or equal to 0.000001865. Got 0.009516487875647071.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 48 at offset 64826 is not less than or equal to 0.000001865. Got 0.009516715715078188.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 49 at offset 66149 is not less than or equal to 0.000001865. Got 0.009893413433050018.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 50 at offset 67472 is not less than or equal to 0.000001865. Got 0.009893580398436517.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 51 at offset 68795 is not less than or equal to 0.000001865. Got 0.010301425392126383.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 52 at offset 70118 is not less than or equal to 0.000001865. Got 0.010301588395931705.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 53 at offset 71441 is not less than or equal to 0.000001865. Got 0.01074447077838395.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 54 at offset 72764 is not less than or equal to 0.000001865. Got 0.010744630049297078.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 55 at offset 74087 is not less than or equal to 0.000001865. Got 0.01122734013080757.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 56 at offset 75410 is not less than or equal to 0.000001865. Got 0.011227562981803465.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 57 at offset 76733 is not less than or equal to 0.000001865. Got 0.011755725728879002.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 58 at offset 78056 is not less than or equal to 0.000001865. Got 0.01175594882979216.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 59 at offset 79379 is not less than or equal to 0.000001865. Got 0.012336223486588924.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 60 at offset 80702 is not less than or equal to 0.000001865. Got 0.012336447834689302.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 61 at offset 82025 is not less than or equal to 0.000001865. Got 0.012977032107613464.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 62 at offset 83348 is not less than or equal to 0.000001865. Got 0.01297733642594461.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 63 at offset 84671 is not less than or equal to 0.000001865. Got 0.013688147253171168.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 64 at offset 85994 is not less than or equal to 0.000001865. Got 0.01368837845955073.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 65 at offset 87317 is not less than or equal to 0.000001865. Got 0.01448162324578537.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 66 at offset 88640 is not less than or equal to 0.000001865. Got 0.01448194743680873.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 67 at offset 89963 is not less than or equal to 0.000001865. Got 0.01537284838487537.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 68 at offset 91286 is not less than or equal to 0.000001865. Got 0.015373187577813849.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 69 at offset 92609 is not less than or equal to 0.000001865. Got 0.016380856349818174.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 70 at offset 93932 is not less than or equal to 0.000001865. Got 0.016381215406334877.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 71 at offset 95255 is not less than or equal to 0.000001865. Got 0.01753033724083315.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 72 at offset 96578 is not less than or equal to 0.000001865. Got 0.017530827271874477.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 73 at offset 97901 is not less than or equal to 0.000001865. Got 0.01885343466700245.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 74 at offset 99224 is not less than or equal to 0.000001865. Got 0.01885396793151646.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 75 at offset 100547 is not less than or equal to 0.000001865. Got 0.020392423027089844.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 76 at offset 101870 is not less than or equal to 0.000001865. Got 0.020393074066344313.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 77 at offset 103193 is not less than or equal to 0.000001865. Got 0.022205070948626313.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 78 at offset 104516 is not less than or equal to 0.000001865. Got 0.022205803665596154.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 79 at offset 105839 is not less than or equal to 0.000001865. Got 0.024371327061931274.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 80 at offset 107162 is not less than or equal to 0.000001865. Got 0.02437224312212655.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 81 at offset 108485 is not less than or equal to 0.000001865. Got 0.027006033852439857.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 82 at offset 109808 is not less than or equal to 0.000001865. Got 0.027007111489952065.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 83 at offset 111131 is not less than or equal to 0.000001865. Got 0.030279442811311768.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 84 at offset 112454 is not less than or equal to 0.000001865. Got 0.03028084076877433.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 85 at offset 113777 is not less than or equal to 0.000001865. Got 0.034455837602666496.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 86 at offset 115100 is not less than or equal to 0.000001865. Got 0.03445758854939049.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 87 at offset 116423 is not less than or equal to 0.000001865. Got 0.039968519116250927.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 88 at offset 117746 is not less than or equal to 0.000001865. Got 0.03997099563742852.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 89 at offset 119069 is not less than or equal to 0.000001865. Got 0.047581336103021205.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 90 at offset 120392 is not less than or equal to 0.000001865. Got 0.047584752923298695.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 91 at offset 121715 is not less than or equal to 0.000001865. Got 0.05877649592226442.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 92 at offset 123038 is not less than or equal to 0.000001865. Got 0.05878170178485925.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 93 at offset 124361 is not less than or equal to 0.000001865. Got 0.07686046970099752.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 94 at offset 125684 is not less than or equal to 0.000001865. Got 0.0768694240525683.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 95 at offset 127007 is not less than or equal to 0.000001865. Got 0.11101781971301485.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 96 at offset 128330 is not less than or equal to 0.000001865. Got 0.11103647207884057.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 97 at offset 129653 is not less than or equal to 0.000001865. Got 0.19981859470557914.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 98 at offset 130976 is not less than or equal to 0.000001865. Got 0.19987906233523942.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 99 at offset 130979 is not less than or equal to 0.000001865. Got 0.0007564072834763206.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test\] 100 out of 102 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audioparam-method-chaining.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,310 @@
|
|||
[audioparam-setTargetAtTime.html]
|
||||
[X Number of tests started and ended at the correct time is not equal to 100. Got 1.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 0 at offset 1322 is not less than or equal to 0.00065683. Got 0.990047280389914.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 1 at offset 1323 is not less than or equal to 0.00065683. Got 0.98989898989899.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 2 at offset 3968 is not less than or equal to 0.00065683. Got 0.9898451435112884.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 3 at offset 3969 is not less than or equal to 0.00065683. Got 0.9896907216494846.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 4 at offset 6614 is not less than or equal to 0.00065683. Got 0.9896346257350639.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 5 at offset 6615 is not less than or equal to 0.00065683. Got 0.9894736842105263.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 6 at offset 9260 is not less than or equal to 0.00065683. Got 0.9894151948002298.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 7 at offset 9261 is not less than or equal to 0.00065683. Got 0.989247311827957.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 8 at offset 11906 is not less than or equal to 0.00065683. Got 0.9891862723999705.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 9 at offset 11907 is not less than or equal to 0.00065683. Got 0.989010989010989.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 10 at offset 14552 is not less than or equal to 0.00065683. Got 0.9889472290923282.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 11 at offset 14553 is not less than or equal to 0.00065683. Got 0.9887640449438202.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 12 at offset 17198 is not less than or equal to 0.00065683. Got 0.9886973785205923.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 13 at offset 17199 is not less than or equal to 0.00065683. Got 0.9885057471264368.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 14 at offset 19844 is not less than or equal to 0.00065683. Got 0.988435970831659.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 15 at offset 19845 is not less than or equal to 0.00065683. Got 0.9882352941176471.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 16 at offset 22490 is not less than or equal to 0.00065683. Got 0.9881621851594479.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 17 at offset 22491 is not less than or equal to 0.00065683. Got 0.9879518072289156.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 18 at offset 25136 is not less than or equal to 0.00065683. Got 0.9878751210146629.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 19 at offset 25137 is not less than or equal to 0.00065683. Got 0.9876543209876543.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 20 at offset 27782 is not less than or equal to 0.00065683. Got 0.9875737883906436.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 21 at offset 27783 is not less than or equal to 0.00065683. Got 0.9873417721518988.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 22 at offset 30428 is not less than or equal to 0.00065683. Got 0.9872570963562539.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 23 at offset 30429 is not less than or equal to 0.00065683. Got 0.987012987012987.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 24 at offset 33074 is not less than or equal to 0.00065683. Got 0.9869238398588358.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 25 at offset 33075 is not less than or equal to 0.00065683. Got 0.9866666666666667.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 26 at offset 35720 is not less than or equal to 0.00065683. Got 0.9865726844007524.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 27 at offset 35721 is not less than or equal to 0.00065683. Got 0.9863013698630136.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 28 at offset 38366 is not less than or equal to 0.00065683. Got 0.9862021481787615.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 29 at offset 38367 is not less than or equal to 0.00065683. Got 0.9859154929577465.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 30 at offset 41012 is not less than or equal to 0.00065683. Got 0.9858105811822068.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 31 at offset 41013 is not less than or equal to 0.00065683. Got 0.9855072463768116.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 32 at offset 43658 is not less than or equal to 0.00065683. Got 0.9853961406282427.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 33 at offset 43659 is not less than or equal to 0.00065683. Got 0.9850746268656716.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 34 at offset 46304 is not less than or equal to 0.00065683. Got 0.9849567619626562.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 35 at offset 46305 is not less than or equal to 0.00065683. Got 0.9846153846153847.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 36 at offset 48950 is not less than or equal to 0.00065683. Got 0.984490124463403.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 37 at offset 48951 is not less than or equal to 0.00065683. Got 0.9841269841269841.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 38 at offset 51596 is not less than or equal to 0.00065683. Got 0.9839936102373862.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 39 at offset 51597 is not less than or equal to 0.00065683. Got 0.9836065573770492.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 40 at offset 54242 is not less than or equal to 0.00065683. Got 0.9834642550810092.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 41 at offset 54243 is not less than or equal to 0.00065683. Got 0.9830508474576272.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 42 at offset 56888 is not less than or equal to 0.00065683. Got 0.9828986892565407.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 43 at offset 56889 is not less than or equal to 0.00065683. Got 0.9824561403508771.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 44 at offset 59534 is not less than or equal to 0.00065683. Got 0.9822930656844523.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 45 at offset 59535 is not less than or equal to 0.00065683. Got 0.9818181818181818.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 46 at offset 62180 is not less than or equal to 0.00065683. Got 0.9816429723176522.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 47 at offset 62181 is not less than or equal to 0.00065683. Got 0.9811320754716981.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 48 at offset 64826 is not less than or equal to 0.00065683. Got 0.9809433244774503.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 49 at offset 64827 is not less than or equal to 0.00065683. Got 0.9803921568627451.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 50 at offset 67472 is not less than or equal to 0.00065683. Got 0.9801882315933432.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 51 at offset 67473 is not less than or equal to 0.00065683. Got 0.9795918367346939.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 52 at offset 70118 is not less than or equal to 0.00065683. Got 0.97937083095423.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 53 at offset 70119 is not less than or equal to 0.00065683. Got 0.9787234042553191.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 54 at offset 72764 is not less than or equal to 0.00065683. Got 0.9784830785336837.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 55 at offset 72765 is not less than or equal to 0.00065683. Got 0.9777777777777777.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 56 at offset 75410 is not less than or equal to 0.00065683. Got 0.9775154833769094.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 57 at offset 75411 is not less than or equal to 0.00065683. Got 0.9767441860465116.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 58 at offset 78056 is not less than or equal to 0.00065683. Got 0.9764567669470277.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 59 at offset 78057 is not less than or equal to 0.00065683. Got 0.975609756097561.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 60 at offset 80702 is not less than or equal to 0.00065683. Got 0.9752934214747024.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 61 at offset 80703 is not less than or equal to 0.00065683. Got 0.9743589743589743.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 62 at offset 83348 is not less than or equal to 0.00065683. Got 0.9740091305612436.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 63 at offset 83349 is not less than or equal to 0.00065683. Got 0.972972972972973.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 64 at offset 85994 is not less than or equal to 0.00065683. Got 0.9725839991647606.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 65 at offset 85995 is not less than or equal to 0.00065683. Got 0.9714285714285714.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 66 at offset 88640 is not less than or equal to 0.00065683. Got 0.9709935155615783.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 67 at offset 88641 is not less than or equal to 0.00065683. Got 0.9696969696969697.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 68 at offset 91286 is not less than or equal to 0.00065683. Got 0.9692071297374057.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 69 at offset 91287 is not less than or equal to 0.00065683. Got 0.967741935483871.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 70 at offset 93932 is not less than or equal to 0.00065683. Got 0.9671862719990767.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 71 at offset 93933 is not less than or equal to 0.00065683. Got 0.9655172413793104.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 72 at offset 96578 is not less than or equal to 0.00065683. Got 0.9648815365865586.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 73 at offset 96579 is not less than or equal to 0.00065683. Got 0.9629629629629629.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 74 at offset 99224 is not less than or equal to 0.00065683. Got 0.9622285887375713.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 75 at offset 99225 is not less than or equal to 0.00065683. Got 0.96.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 76 at offset 101870 is not less than or equal to 0.00065683. Got 0.9591420650055538.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 77 at offset 101871 is not less than or equal to 0.00065683. Got 0.9565217391304348.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 78 at offset 104516 is not less than or equal to 0.00065683. Got 0.9555062168024705.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 79 at offset 104517 is not less than or equal to 0.00065683. Got 0.9523809523809523.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 80 at offset 107162 is not less than or equal to 0.00065683. Got 0.9511600703170818.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 81 at offset 107163 is not less than or equal to 0.00065683. Got 0.9473684210526315.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 82 at offset 109808 is not less than or equal to 0.00065683. Got 0.9458729474346069.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 83 at offset 109809 is not less than or equal to 0.00065683. Got 0.9411764705882352.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 84 at offset 112454 is not less than or equal to 0.00065683. Got 0.939302156727807.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 85 at offset 112455 is not less than or equal to 0.00065683. Got 0.9333333333333333.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 86 at offset 115100 is not less than or equal to 0.00065683. Got 0.9309156097430662.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 87 at offset 115101 is not less than or equal to 0.00065683. Got 0.9230769230769231.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 88 at offset 117746 is not less than or equal to 0.00065683. Got 0.9198400003447016.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 89 at offset 117747 is not less than or equal to 0.00065683. Got 0.9090909090909091.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 90 at offset 120392 is not less than or equal to 0.00065683. Got 0.9045350614645049.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 91 at offset 120393 is not less than or equal to 0.00065683. Got 0.8888888888888888.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 92 at offset 123038 is not less than or equal to 0.00065683. Got 0.8820065951886947.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 93 at offset 123039 is not less than or equal to 0.00065683. Got 0.8571428571428571.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 94 at offset 125684 is not less than or equal to 0.00065683. Got 0.845561037037827.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 95 at offset 125685 is not less than or equal to 0.00065683. Got 0.8.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 96 at offset 128330 is not less than or equal to 0.00065683. Got 0.776538807317465.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 97 at offset 128331 is not less than or equal to 0.00065683. Got 0.6666666666666642.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 98 at offset 130976 is not less than or equal to 0.00065683. Got 0.595967750692577.]
|
||||
expected: FAIL
|
||||
|
||||
[X Max error for test 99 at offset 132299 is not less than or equal to 0.00065683. Got 0.9049431604462704.]
|
||||
expected: FAIL
|
||||
|
||||
[< [test\] 101 out of 102 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
[audioparam-setValueCurve-exceptions.html]
|
||||
expected: ERROR
|
||||
[X setValueCurveAtTime(curve, 0.0125, 0.0125) incorrectly threw TypeError: "g.gain.setValueCurveAtTime is not a function".]
|
||||
expected: FAIL
|
||||
|
||||
[X setValueAtTime(1, 0.018750000000000003) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X linearRampToValueAtTime(1, 0.018750000000000003) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X exponentialRampToValueAtTime(1, 0.018750000000000003) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X setTargetAtTime(1, 0.018750000000000003, 1) did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[< [setValueCurve\] 5 out of 6 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X setValueCurveAtTime(curve, 0.05, 0.1) incorrectly threw TypeError: "g.gain.setValueCurveAtTime is not a function".]
|
||||
expected: FAIL
|
||||
|
||||
[X setValueCurveAtTime(curve, 0.00625, 0.01) threw "TypeError" instead of NotSupportedError.]
|
||||
expected: FAIL
|
||||
|
||||
[X setValueCurveAtTime(curve, 0.018750000000000003, 0.01) threw "TypeError" instead of NotSupportedError.]
|
||||
expected: FAIL
|
||||
|
||||
[X setValueCurveAtTime(curve, 0.03125, 0.01) threw "TypeError" instead of NotSupportedError.]
|
||||
expected: FAIL
|
||||
|
||||
[X setValueCurveAtTime(curve, 0.043750000000000004, 0.01) threw "TypeError" instead of NotSupportedError.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[audioparam-setValueCurveAtTime.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[audioparam-summingjunction.html]
|
||||
expected: CRASH
|
|
@ -0,0 +1,11 @@
|
|||
[automation-rate.html]
|
||||
expected: ERROR
|
||||
[X Set AudioBufferSourceNode.detune.automationRate to "a-rate" did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[X Set AudioBufferSourceNode.playbackRate.automationRate to "a-rate" did not throw an exception.]
|
||||
expected: FAIL
|
||||
|
||||
[< [AudioBufferSourceNode\] 2 out of 4 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[event-insertion.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-audioworklet.https.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-biquad.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-constant-source.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-delay.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-gain.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-oscillator.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-panner.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[k-rate-stereo-panner.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[retrospective-exponentialRampToValueAtTime.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[retrospective-linearRampToValueAtTime.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[retrospective-setTargetAtTime.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[retrospective-setValueAtTime.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,2 @@
|
|||
[retrospective-setValueCurveAtTime.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,4 @@
|
|||
[setTargetAtTime-after-event-within-block.html]
|
||||
[Test setTargetAtTime after an event in the same processing block]
|
||||
expected: FAIL
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue