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:
bors-servo 2018-07-31 09:00:06 -04:00 committed by GitHub
commit 0051597525
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
199 changed files with 5178 additions and 25 deletions

View file

@ -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
View file

@ -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"

View file

@ -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`.

View file

@ -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

View file

@ -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

View file

@ -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`

View file

@ -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"]}

View file

@ -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"]}

View file

@ -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"

View 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(())
}
}

View 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,
}
}
}

View 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(),
}
}
}

View 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
}
}

View 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,
}
}
}

View 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,
}
}
}

View 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(())
}
}

View 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,
}
}
}

View file

@ -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> {

View file

@ -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]

View 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,
}
}
}

View file

@ -629,3 +629,4 @@ macro_rules! handle_potential_webgl_error {
handle_potential_webgl_error!($context, $call, ());
};
}

View file

@ -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;

View 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()
}
}

View 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
}
}

View 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,
}
}
}

View 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);
};

View 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);
};

View 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();
};

View 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;
};

View 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;
};

View 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);
};

View file

@ -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);
};

View 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);
};

View 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;
};

View 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/. */
/*
* 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;
};

View 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);
};

View 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);
};

View file

@ -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;

View file

@ -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"

View file

@ -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"}

View file

@ -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."

View file

@ -107,6 +107,8 @@ skip: true
skip: false
[url]
skip: false
[webaudio]
skip: false
[WebCryptoAPI]
skip: false
[webgl]

View 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

View file

@ -0,0 +1,4 @@
[idlharness.https.window.html]
[idlharness]
expected: FAIL

View file

@ -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

View file

@ -0,0 +1,2 @@
[realtimeanalyser-basic.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[realtimeanalyser-fft-scaling.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[realtimeanalyser-fft-sizing.html]
expected: ERROR

View file

@ -0,0 +1,4 @@
[test-analyser-gain.html]
[Test effect of AnalyserNode on GainNode output]
expected: FAIL

View file

@ -0,0 +1,4 @@
[test-analyser-minimum.html]
[Test AnalyserNode when the input is silent]
expected: FAIL

View file

@ -0,0 +1,4 @@
[test-analyser-output.html]
[AnalyserNode output]
expected: FAIL

View file

@ -0,0 +1,4 @@
[test-analyser-scale.html]
[Test AnalyserNode when the input is scaled]
expected: FAIL

View file

@ -0,0 +1,7 @@
[test-analysernode.html]
[Test AnalyserNode API]
expected: FAIL
[Test AnalyserNode's ctor API]
expected: FAIL

View file

@ -0,0 +1,2 @@
[audiobuffer-copy-channel.html]
expected: CRASH

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
[audiobuffersource-ended.html]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[audiobuffersource-multi-channels.html]
expected: TIMEOUT

View file

@ -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

View file

@ -0,0 +1,2 @@
[audiobuffersource-playbackrate-zero.html]
expected: CRASH

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
[note-grain-on-play.html]
expected: CRASH

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
[audionode-channel-rules.html]
expected: CRASH

View file

@ -0,0 +1,2 @@
[audionode-connect-method-chaining.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[audionode-connect-order.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[audionode-disconnect-audioparam.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[audionode-disconnect.html]
expected: TIMEOUT

View file

@ -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

View file

@ -0,0 +1,2 @@
[audioparam-connect-audioratesignal.html]
expected: CRASH

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
[audioparam-method-chaining.html]
expected: ERROR

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
[audioparam-setValueCurveAtTime.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[audioparam-summingjunction.html]
expected: CRASH

View file

@ -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

View file

@ -0,0 +1,2 @@
[event-insertion.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-audioworklet.https.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-biquad.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-constant-source.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-delay.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-gain.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-oscillator.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-panner.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[k-rate-stereo-panner.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[retrospective-exponentialRampToValueAtTime.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[retrospective-linearRampToValueAtTime.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[retrospective-setTargetAtTime.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[retrospective-setValueAtTime.html]
expected: ERROR

View file

@ -0,0 +1,2 @@
[retrospective-setValueCurveAtTime.html]
expected: ERROR

View file

@ -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