diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index e07c45bc0c..b1f5bf5f87 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -659,6 +659,7 @@ set(SOURCES WebAudio/AudioBuffer.cpp WebAudio/AudioContext.cpp WebAudio/BaseAudioContext.cpp + WebAudio/OfflineAudioContext.cpp WebDriver/Capabilities.cpp WebDriver/Client.cpp WebDriver/Contexts.cpp diff --git a/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.cpp b/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.cpp new file mode 100644 index 0000000000..3c94b9baf7 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024, Shannon Booth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::WebAudio { + +JS_DEFINE_ALLOCATOR(OfflineAudioContext); + +WebIDL::ExceptionOr> OfflineAudioContext::construct_impl(JS::Realm& realm, OfflineAudioContextOptions const& context_options) +{ + return construct_impl(realm, context_options.number_of_channels, context_options.length, context_options.sample_rate); +} + +// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-offlineaudiocontext-numberofchannels-length-samplerate +WebIDL::ExceptionOr> OfflineAudioContext::construct_impl(JS::Realm& realm, + WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate) +{ + // The OfflineAudioContext can be constructed with the same arguments as AudioContext.createBuffer. + // A NotSupportedError exception MUST be thrown if any of the arguments is negative, zero, or outside its nominal range. + TRY(verify_audio_options_inside_nominal_range(realm, number_of_channels, length, sample_rate)); + + return realm.heap().allocate(realm, realm, number_of_channels, length, sample_rate); +} + +OfflineAudioContext::~OfflineAudioContext() = default; + +// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering +WebIDL::ExceptionOr> OfflineAudioContext::start_rendering() +{ + return WebIDL::NotSupportedError::create(realm(), "FIXME: Implement OfflineAudioContext::start_rendering"_fly_string); +} + +WebIDL::ExceptionOr> OfflineAudioContext::resume() +{ + return WebIDL::NotSupportedError::create(realm(), "FIXME: Implement OfflineAudioContext::resume"_fly_string); +} + +WebIDL::ExceptionOr> OfflineAudioContext::suspend(double suspend_time) +{ + (void)suspend_time; + return WebIDL::NotSupportedError::create(realm(), "FIXME: Implement OfflineAudioContext::suspend"_fly_string); +} + +// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-length +WebIDL::UnsignedLong OfflineAudioContext::length() const +{ + // The size of the buffer in sample-frames. This is the same as the value of the length parameter for the constructor. + return m_length; +} + +// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-oncomplete +JS::GCPtr OfflineAudioContext::oncomplete() +{ + return event_handler_attribute(HTML::EventNames::complete); +} + +// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-oncomplete +void OfflineAudioContext::set_oncomplete(JS::GCPtr value) +{ + set_event_handler_attribute(HTML::EventNames::complete, value); +} + +OfflineAudioContext::OfflineAudioContext(JS::Realm& realm, OfflineAudioContextOptions const&) + : BaseAudioContext(realm) +{ +} + +OfflineAudioContext::OfflineAudioContext(JS::Realm& realm, WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate) + : BaseAudioContext(realm) + , m_length(length) +{ + (void)number_of_channels; + (void)sample_rate; +} + +void OfflineAudioContext::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(OfflineAudioContext); +} + +void OfflineAudioContext::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); +} + +} diff --git a/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.h b/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.h new file mode 100644 index 0000000000..a9c70c9dca --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, Shannon Booth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Web::WebAudio { + +// https://webaudio.github.io/web-audio-api/#OfflineAudioContextOptions +struct OfflineAudioContextOptions { + WebIDL::UnsignedLong number_of_channels { 1 }; + WebIDL::UnsignedLong length {}; + float sample_rate {}; +}; + +// https://webaudio.github.io/web-audio-api/#OfflineAudioContext +class OfflineAudioContext final : public BaseAudioContext { + WEB_PLATFORM_OBJECT(OfflineAudioContext, BaseAudioContext); + JS_DECLARE_ALLOCATOR(OfflineAudioContext); + +public: + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, OfflineAudioContextOptions const&); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, + WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate); + + virtual ~OfflineAudioContext() override; + + WebIDL::ExceptionOr> start_rendering(); + WebIDL::ExceptionOr> resume(); + WebIDL::ExceptionOr> suspend(double suspend_time); + + WebIDL::UnsignedLong length() const; + + JS::GCPtr oncomplete(); + void set_oncomplete(JS::GCPtr); + +private: + OfflineAudioContext(JS::Realm&, OfflineAudioContextOptions const&); + OfflineAudioContext(JS::Realm&, WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate); + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; + + WebIDL::UnsignedLong m_length {}; +}; + +} diff --git a/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.idl b/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.idl new file mode 100644 index 0000000000..69d7d693c6 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/OfflineAudioContext.idl @@ -0,0 +1,21 @@ +#import + +// https://webaudio.github.io/web-audio-api/#OfflineAudioContextOptions +dictionary OfflineAudioContextOptions { + unsigned long numberOfChannels = 1; + required unsigned long length; + required float sampleRate; + // FIXME: (AudioContextRenderSizeCategory or unsigned long) renderSizeHint = "default"; +}; + +// https://webaudio.github.io/web-audio-api/#OfflineAudioContext +[Exposed=Window] +interface OfflineAudioContext : BaseAudioContext { + constructor(OfflineAudioContextOptions contextOptions); + constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate); + Promise startRendering(); + Promise resume(); + Promise suspend(double suspendTime); + readonly attribute unsigned long length; + attribute EventHandler oncomplete; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index a32c60709b..799dc0b0ee 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -296,6 +296,7 @@ libweb_js_bindings(WebAssembly/WebAssembly NAMESPACE) libweb_js_bindings(WebAudio/AudioBuffer) libweb_js_bindings(WebAudio/AudioContext) libweb_js_bindings(WebAudio/BaseAudioContext) +libweb_js_bindings(WebAudio/OfflineAudioContext) libweb_js_bindings(WebGL/WebGLContextEvent) libweb_js_bindings(WebGL/WebGLRenderingContext) libweb_js_bindings(WebIDL/DOMException)