diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index bd84ad92f0d..c1be2836bb7 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -35,6 +35,7 @@ static bool is_platform_object(Type const& type) "AnimationTimeline"sv, "Attr"sv, "AudioBuffer"sv, + "AudioListener"sv, "AudioNode"sv, "AudioParam"sv, "AudioScheduledSourceNode"sv, diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn index 1a70a024896..39f505d38ec 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn @@ -12,6 +12,8 @@ source_set("WebAudio") { "AudioContext.h", "AudioDestinationNode.cpp", "AudioDestinationNode.h", + "AudioListener.cpp", + "AudioListener.h", "AudioNode.cpp", "AudioNode.h", "AudioParam.cpp", diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index 8fd08a979dc..af50c3a93f7 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -351,6 +351,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioContext.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioDestinationNode.idl", + "//Userland/Libraries/LibWeb/WebAudio/AudioListener.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioNode.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioParam.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioScheduledSourceNode.idl", diff --git a/Tests/LibWeb/Text/expected/WebAudio/AudioListener.txt b/Tests/LibWeb/Text/expected/WebAudio/AudioListener.txt new file mode 100644 index 00000000000..357cf09e3ce --- /dev/null +++ b/Tests/LibWeb/Text/expected/WebAudio/AudioListener.txt @@ -0,0 +1,18 @@ +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: -1, default: -1, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 1, default: 1, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 0, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: -1, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 2.5, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: -3, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 4, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: -5, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 6, default: -1, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 7, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: -8, default: 1, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate +[object AudioParam] current: 9, default: 0, min: -3.4028234663852886e+38, max: 3.4028234663852886e+38, rate: a-rate diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index f7fc93d2f55..97f1c98cb87 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -15,6 +15,7 @@ AudioBuffer AudioBufferSourceNode AudioContext AudioDestinationNode +AudioListener AudioNode AudioParam AudioScheduledSourceNode diff --git a/Tests/LibWeb/Text/input/WebAudio/AudioListener.html b/Tests/LibWeb/Text/input/WebAudio/AudioListener.html new file mode 100644 index 00000000000..eb126cf938a --- /dev/null +++ b/Tests/LibWeb/Text/input/WebAudio/AudioListener.html @@ -0,0 +1,29 @@ + + diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 2fb44f7ad3e..91492f7696a 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -725,6 +725,7 @@ set(SOURCES WebAudio/AudioBufferSourceNode.cpp WebAudio/AudioContext.cpp WebAudio/AudioDestinationNode.cpp + WebAudio/AudioListener.cpp WebAudio/AudioNode.cpp WebAudio/AudioParam.cpp WebAudio/AudioScheduledSourceNode.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index c6707ca033f..53d1ac812fe 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -768,6 +768,7 @@ class AudioBuffer; class AudioBufferSourceNode; class AudioContext; class AudioDestinationNode; +class AudioListener; class AudioNode; class AudioParam; class AudioScheduledSourceNode; diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioListener.cpp b/Userland/Libraries/LibWeb/WebAudio/AudioListener.cpp new file mode 100644 index 00000000000..2df7ce2f565 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/AudioListener.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024, Jelle Raaijmakers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::WebAudio { + +JS_DEFINE_ALLOCATOR(AudioListener); + +AudioListener::AudioListener(JS::Realm& realm) + : Bindings::PlatformObject(realm) + , m_forward_x(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_forward_y(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_forward_z(AudioParam::create(realm, -1.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_x(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_y(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_z(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_up_x(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_up_y(AudioParam::create(realm, 1.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_up_z(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) +{ +} + +JS::NonnullGCPtr AudioListener::create(JS::Realm& realm) +{ + return realm.vm().heap().allocate(realm, realm); +} + +AudioListener::~AudioListener() = default; + +// https://webaudio.github.io/web-audio-api/#dom-audiolistener-setposition +WebIDL::ExceptionOr AudioListener::set_position(float x, float y, float z) +{ + // This method is DEPRECATED. It is equivalent to setting positionX.value, positionY.value, and + // positionZ.value directly with the given x, y, and z values, respectively. + + // FIXME: Consequently, any of the positionX, positionY, and positionZ AudioParams for this + // AudioListener have an automation curve set using setValueCurveAtTime() at the time this + // method is called, a NotSupportedError MUST be thrown. + + m_position_x->set_value(x); + m_position_y->set_value(y); + m_position_z->set_value(z); + + return {}; +} + +// https://webaudio.github.io/web-audio-api/#dom-audiolistener-setorientation +WebIDL::ExceptionOr AudioListener::set_orientation(float x, float y, float z, float x_up, float y_up, float z_up) +{ + // This method is DEPRECATED. It is equivalent to setting forwardX.value, forwardY.value, + // forwardZ.value, upX.value, upY.value, and upZ.value directly with the given x, y, z, xUp, + // yUp, and zUp values, respectively. + + // FIXME: Consequently, if any of the forwardX, forwardY, forwardZ, upX, upY and upZ + // AudioParams have an automation curve set using setValueCurveAtTime() at the time this + // method is called, a NotSupportedError MUST be thrown. + + m_forward_x->set_value(x); + m_forward_y->set_value(y); + m_forward_z->set_value(z); + m_up_x->set_value(x_up); + m_up_y->set_value(y_up); + m_up_z->set_value(z_up); + + return {}; +} + +void AudioListener::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(AudioListener); +} + +void AudioListener::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_forward_x); + visitor.visit(m_forward_y); + visitor.visit(m_forward_z); + visitor.visit(m_position_x); + visitor.visit(m_position_y); + visitor.visit(m_position_z); + visitor.visit(m_up_x); + visitor.visit(m_up_y); + visitor.visit(m_up_z); +} + +} diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioListener.h b/Userland/Libraries/LibWeb/WebAudio/AudioListener.h new file mode 100644 index 00000000000..ba4a361097a --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/AudioListener.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024, Jelle Raaijmakers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Web::WebAudio { + +// https://webaudio.github.io/web-audio-api/#AudioListener +class AudioListener final : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(AudioListener, Bindings::PlatformObject); + JS_DECLARE_ALLOCATOR(AudioListener); + +public: + static JS::NonnullGCPtr create(JS::Realm&); + virtual ~AudioListener() override; + + JS::NonnullGCPtr forward_x() const { return m_forward_x; } + JS::NonnullGCPtr forward_y() const { return m_forward_y; } + JS::NonnullGCPtr forward_z() const { return m_forward_z; } + JS::NonnullGCPtr position_x() const { return m_position_x; } + JS::NonnullGCPtr position_y() const { return m_position_y; } + JS::NonnullGCPtr position_z() const { return m_position_z; } + JS::NonnullGCPtr up_x() const { return m_up_x; } + JS::NonnullGCPtr up_y() const { return m_up_y; } + JS::NonnullGCPtr up_z() const { return m_up_z; } + + WebIDL::ExceptionOr set_position(float x, float y, float z); + WebIDL::ExceptionOr set_orientation(float x, float y, float z, float x_up, float y_up, float z_up); + +private: + explicit AudioListener(JS::Realm&); + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr m_forward_x; + JS::NonnullGCPtr m_forward_y; + JS::NonnullGCPtr m_forward_z; + JS::NonnullGCPtr m_position_x; + JS::NonnullGCPtr m_position_y; + JS::NonnullGCPtr m_position_z; + JS::NonnullGCPtr m_up_x; + JS::NonnullGCPtr m_up_y; + JS::NonnullGCPtr m_up_z; +}; + +} diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioListener.idl b/Userland/Libraries/LibWeb/WebAudio/AudioListener.idl new file mode 100644 index 00000000000..3afa47fea5d --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/AudioListener.idl @@ -0,0 +1,15 @@ +// https://webaudio.github.io/web-audio-api/#AudioListener +[Exposed=Window] +interface AudioListener { + readonly attribute AudioParam positionX; + readonly attribute AudioParam positionY; + readonly attribute AudioParam positionZ; + readonly attribute AudioParam forwardX; + readonly attribute AudioParam forwardY; + readonly attribute AudioParam forwardZ; + readonly attribute AudioParam upX; + readonly attribute AudioParam upY; + readonly attribute AudioParam upZ; + undefined setPosition (float x, float y, float z); + undefined setOrientation (float x, float y, float z, float xUp, float yUp, float zUp); +}; diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp index 49c0c368cc1..ddd6451573a 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp @@ -28,6 +28,7 @@ BaseAudioContext::BaseAudioContext(JS::Realm& realm, float sample_rate) : DOM::EventTarget(realm) , m_destination(AudioDestinationNode::construct_impl(realm, *this)) , m_sample_rate(sample_rate) + , m_listener(AudioListener::create(realm)) { } @@ -44,6 +45,7 @@ void BaseAudioContext::visit_edges(Cell::Visitor& visitor) Base::visit_edges(visitor); visitor.visit(m_destination); visitor.visit(m_pending_promises); + visitor.visit(m_listener); } void BaseAudioContext::set_onstatechange(WebIDL::CallbackType* event_handler) diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h index c216a7c24ee..27b10eb9cf5 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -38,6 +39,7 @@ public: JS::NonnullGCPtr destination() const { return m_destination; } float sample_rate() const { return m_sample_rate; } double current_time() const { return m_current_time; } + JS::NonnullGCPtr listener() const { return m_listener; } Bindings::AudioContextState state() const { return m_control_thread_state; } // https://webaudio.github.io/web-audio-api/#--nyquist-frequency @@ -78,6 +80,8 @@ private: float m_sample_rate { 0 }; double m_current_time { 0 }; + JS::NonnullGCPtr m_listener; + Bindings::AudioContextState m_control_thread_state = Bindings::AudioContextState::Suspended; Bindings::AudioContextState m_rendering_thread_state = Bindings::AudioContextState::Suspended; diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl index e5acc435e55..79b887fc50e 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl @@ -3,6 +3,7 @@ #import #import #import +#import #import #import #import @@ -21,7 +22,7 @@ interface BaseAudioContext : EventTarget { readonly attribute AudioDestinationNode destination; readonly attribute float sampleRate; readonly attribute double currentTime; - [FIXME] readonly attribute AudioListener listener; + readonly attribute AudioListener listener; readonly attribute AudioContextState state; // FIXME: [SameObject, SecureContext] [FIXME] readonly attribute AudioWorklet audioWorklet; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 7e0abf596ff..e7cc62c322a 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -337,6 +337,7 @@ libweb_js_bindings(WebAudio/AudioBuffer) libweb_js_bindings(WebAudio/AudioBufferSourceNode) libweb_js_bindings(WebAudio/AudioContext) libweb_js_bindings(WebAudio/AudioDestinationNode) +libweb_js_bindings(WebAudio/AudioListener) libweb_js_bindings(WebAudio/AudioNode) libweb_js_bindings(WebAudio/AudioParam) libweb_js_bindings(WebAudio/AudioScheduledSourceNode)