/* * Copyright (c) 2020, the SerenityOS developers. * Copyright (c) 2023, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include namespace Web::HTML { class HTMLMediaElement : public HTMLElement { WEB_PLATFORM_OBJECT(HTMLMediaElement, HTMLElement); public: virtual ~HTMLMediaElement() override; void queue_a_media_element_task(JS::SafeFunction steps); enum class NetworkState : u16 { Empty, Idle, Loading, NoSource, }; NetworkState network_state() const { return m_network_state; } WebIDL::ExceptionOr can_play_type(DeprecatedString const& type) const; enum class ReadyState : u16 { HaveNothing, HaveMetadata, HaveCurrentData, HaveFutureData, HaveEnoughData, }; ReadyState ready_state() const { return m_ready_state; } WebIDL::ExceptionOr load(); double current_time() const; void set_current_time(double); void set_current_playback_position(double); double duration() const; bool paused() const { return m_paused; } bool ended() const; WebIDL::ExceptionOr> play(); WebIDL::ExceptionOr pause(); JS::NonnullGCPtr video_tracks() const { return *m_video_tracks; } protected: HTMLMediaElement(DOM::Document&, DOM::QualifiedName); virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; // Override in subclasses to handle implementation-specific behavior when the element state changes // to playing or paused, e.g. to start/stop play timers. virtual void on_playing() { } virtual void on_paused() { } private: struct EntireResource { }; using ByteRange = Variant; // FIXME: This will need to include "until end" and an actual byte range. virtual void parse_attribute(DeprecatedFlyString const& name, DeprecatedString const& value) override; Task::Source media_element_event_task_source() const { return m_media_element_event_task_source.source; } WebIDL::ExceptionOr load_element(); WebIDL::ExceptionOr select_resource(); WebIDL::ExceptionOr fetch_resource(AK::URL const&, Function failure_callback); static bool verify_response(JS::NonnullGCPtr, ByteRange const&); WebIDL::ExceptionOr process_media_data(Function failure_callback); WebIDL::ExceptionOr handle_media_source_failure(Span> promises); void forget_media_resource_specific_tracks(); void set_ready_state(ReadyState); WebIDL::ExceptionOr play_element(); WebIDL::ExceptionOr pause_element(); void notify_about_playing(); void set_paused(bool); void set_duration(double); bool has_ended_playback() const; WebIDL::ExceptionOr reached_end_of_media_playback(); WebIDL::ExceptionOr dispatch_time_update_event(); enum class TimeMarchesOnReason { NormalPlayback, Other, }; void time_marches_on(TimeMarchesOnReason = TimeMarchesOnReason::NormalPlayback); JS::MarkedVector> take_pending_play_promises(); void resolve_pending_play_promises(ReadonlySpan> promises); void reject_pending_play_promises(ReadonlySpan> promises, JS::NonnullGCPtr error); // https://html.spec.whatwg.org/multipage/media.html#reject-pending-play-promises template void reject_pending_play_promises(ReadonlySpan> promises, FlyString const& message) { auto& realm = this->realm(); auto error = ErrorType::create(realm, message.to_deprecated_fly_string()); reject_pending_play_promises(promises, error); } // https://html.spec.whatwg.org/multipage/media.html#media-element-event-task-source UniqueTaskSource m_media_element_event_task_source {}; // https://html.spec.whatwg.org/multipage/media.html#dom-media-networkstate NetworkState m_network_state { NetworkState::Empty }; // https://html.spec.whatwg.org/multipage/media.html#dom-media-readystate ReadyState m_ready_state { ReadyState::HaveNothing }; bool m_first_data_load_event_since_load_start { false }; // https://html.spec.whatwg.org/multipage/media.html#current-playback-position double m_current_playback_position { 0 }; // https://html.spec.whatwg.org/multipage/media.html#official-playback-position double m_official_playback_position { 0 }; // https://html.spec.whatwg.org/multipage/media.html#default-playback-start-position double m_default_playback_start_position { 0 }; // https://html.spec.whatwg.org/multipage/media.html#dom-media-duration double m_duration { NAN }; // https://html.spec.whatwg.org/multipage/media.html#list-of-pending-play-promises JS::MarkedVector> m_pending_play_promises; // https://html.spec.whatwg.org/multipage/media.html#dom-media-paused bool m_paused { true }; // https://html.spec.whatwg.org/multipage/media.html#dom-media-videotracks JS::GCPtr m_video_tracks; // https://html.spec.whatwg.org/multipage/media.html#media-data ByteBuffer m_media_data; bool m_running_time_update_event_handler { false }; Optional