/src/serenity/Userland/Libraries/LibWeb/HTML/AudioTrack.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/IDAllocator.h> |
8 | | #include <LibAudio/Loader.h> |
9 | | #include <LibJS/Runtime/Realm.h> |
10 | | #include <LibJS/Runtime/VM.h> |
11 | | #include <LibWeb/Bindings/AudioTrackPrototype.h> |
12 | | #include <LibWeb/Bindings/Intrinsics.h> |
13 | | #include <LibWeb/DOM/Event.h> |
14 | | #include <LibWeb/HTML/AudioTrack.h> |
15 | | #include <LibWeb/HTML/AudioTrackList.h> |
16 | | #include <LibWeb/HTML/EventNames.h> |
17 | | #include <LibWeb/HTML/HTMLMediaElement.h> |
18 | | #include <LibWeb/Layout/Node.h> |
19 | | #include <LibWeb/Painting/Paintable.h> |
20 | | #include <LibWeb/Platform/AudioCodecPlugin.h> |
21 | | |
22 | | namespace Web::HTML { |
23 | | |
24 | | JS_DEFINE_ALLOCATOR(AudioTrack); |
25 | | |
26 | | static IDAllocator s_audio_track_id_allocator; |
27 | | |
28 | | AudioTrack::AudioTrack(JS::Realm& realm, JS::NonnullGCPtr<HTMLMediaElement> media_element, NonnullRefPtr<Audio::Loader> loader) |
29 | 0 | : PlatformObject(realm) |
30 | 0 | , m_media_element(media_element) |
31 | 0 | , m_audio_plugin(Platform::AudioCodecPlugin::create(move(loader)).release_value_but_fixme_should_propagate_errors()) |
32 | 0 | { |
33 | 0 | m_audio_plugin->on_playback_position_updated = [this](auto position) { |
34 | 0 | if (auto const* paintable = m_media_element->paintable()) |
35 | 0 | paintable->set_needs_display(); |
36 | |
|
37 | 0 | auto playback_position = static_cast<double>(position.to_milliseconds()) / 1000.0; |
38 | 0 | m_media_element->set_current_playback_position(playback_position); |
39 | 0 | }; |
40 | |
|
41 | 0 | m_audio_plugin->on_decoder_error = [this](String error_message) { |
42 | 0 | m_media_element->set_decoder_error(move(error_message)); |
43 | 0 | }; |
44 | 0 | } |
45 | | |
46 | | AudioTrack::~AudioTrack() |
47 | 0 | { |
48 | 0 | auto id = m_id.to_number<int>(); |
49 | 0 | VERIFY(id.has_value()); |
50 | | |
51 | 0 | s_audio_track_id_allocator.deallocate(id.value()); |
52 | 0 | } |
53 | | |
54 | | void AudioTrack::initialize(JS::Realm& realm) |
55 | 0 | { |
56 | 0 | Base::initialize(realm); |
57 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(AudioTrack); |
58 | |
|
59 | 0 | auto id = s_audio_track_id_allocator.allocate(); |
60 | 0 | m_id = String::number(id); |
61 | 0 | } |
62 | | |
63 | | void AudioTrack::play(Badge<HTMLAudioElement>) |
64 | 0 | { |
65 | 0 | m_audio_plugin->resume_playback(); |
66 | 0 | } |
67 | | |
68 | | void AudioTrack::pause(Badge<HTMLAudioElement>) |
69 | 0 | { |
70 | 0 | m_audio_plugin->pause_playback(); |
71 | 0 | } |
72 | | |
73 | | AK::Duration AudioTrack::duration() |
74 | 0 | { |
75 | 0 | return m_audio_plugin->duration(); |
76 | 0 | } |
77 | | |
78 | | void AudioTrack::seek(double position, MediaSeekMode seek_mode) |
79 | 0 | { |
80 | | // FIXME: Implement seeking mode. |
81 | 0 | (void)seek_mode; |
82 | |
|
83 | 0 | m_audio_plugin->seek(position); |
84 | 0 | } |
85 | | |
86 | | void AudioTrack::update_volume() |
87 | 0 | { |
88 | 0 | m_audio_plugin->set_volume(m_media_element->effective_media_volume()); |
89 | 0 | } |
90 | | |
91 | | void AudioTrack::visit_edges(Cell::Visitor& visitor) |
92 | 0 | { |
93 | 0 | Base::visit_edges(visitor); |
94 | 0 | visitor.visit(m_media_element); |
95 | 0 | visitor.visit(m_audio_track_list); |
96 | 0 | } |
97 | | |
98 | | // https://html.spec.whatwg.org/multipage/media.html#dom-audiotrack-enabled |
99 | | void AudioTrack::set_enabled(bool enabled) |
100 | 0 | { |
101 | | // On setting, it must enable the track if the new value is true, and disable it otherwise. (If the track is no |
102 | | // longer in an AudioTrackList object, then the track being enabled or disabled has no effect beyond changing the |
103 | | // value of the attribute on the AudioTrack object.) |
104 | 0 | if (m_enabled == enabled) |
105 | 0 | return; |
106 | | |
107 | 0 | if (m_audio_track_list) { |
108 | | // Whenever an audio track in an AudioTrackList that was disabled is enabled, and whenever one that was enabled |
109 | | // is disabled, the user agent must queue a media element task given the media element to fire an event named |
110 | | // change at the AudioTrackList object. |
111 | 0 | m_media_element->queue_a_media_element_task([this]() { |
112 | 0 | m_audio_track_list->dispatch_event(DOM::Event::create(realm(), HTML::EventNames::change)); |
113 | 0 | }); |
114 | 0 | } |
115 | |
|
116 | 0 | m_enabled = enabled; |
117 | 0 | } |
118 | | |
119 | | } |