mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-05-11 17:37:33 +02:00
Previously we were inconsistent by generating code for enum definitions but not generating code for dictionaries. With future changes to the IDL generator to expose helpers to convert to and from IDL values this produced circular depdendencies. To solve this problem, also generate the dictionary definitions in bindings headers.
198 lines
6.9 KiB
C++
198 lines
6.9 KiB
C++
/*
|
|
* Copyright (c) 2026, The Ladybird developers
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/Bindings/Intrinsics.h>
|
|
#include <LibWeb/Bindings/MediaStream.h>
|
|
#include <LibWeb/Bindings/MediaStreamTrack.h>
|
|
#include <LibWeb/Bindings/MediaStreamTrackEvent.h>
|
|
#include <LibWeb/Crypto/Crypto.h>
|
|
#include <LibWeb/HTML/EventNames.h>
|
|
#include <LibWeb/MediaCapture/MediaStream.h>
|
|
#include <LibWeb/MediaCapture/MediaStreamTrackEvent.h>
|
|
|
|
namespace Web::MediaCapture {
|
|
|
|
GC_DEFINE_ALLOCATOR(MediaStream);
|
|
|
|
MediaStream::MediaStream(JS::Realm& realm)
|
|
: DOM::EventTarget(realm)
|
|
{
|
|
}
|
|
|
|
GC::Ref<MediaStream> MediaStream::create(JS::Realm& realm)
|
|
{
|
|
auto stream = realm.create<MediaStream>(realm);
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-id
|
|
stream->m_id = Crypto::generate_random_uuid();
|
|
return stream;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#mediastream
|
|
GC::Ref<MediaStream> MediaStream::construct_impl(JS::Realm& realm, Vector<GC::Root<MediaStreamTrack>> const& tracks)
|
|
{
|
|
// 1. Let stream be a newly constructed MediaStream object.
|
|
// 2. Initialize stream.id attribute to a newly generated value.
|
|
auto stream = create(realm);
|
|
|
|
// 3. If the constructor's argument is present, run the following steps:
|
|
// 3.1. Construct a set of tracks tracks based on the type of argument.
|
|
// 3.2. For each MediaStreamTrack, track, in tracks:
|
|
for (auto const& track : tracks) {
|
|
// 3.2.1. If track is already in stream's track set, skip track.
|
|
// 3.2.2. Otherwise, add track to stream's track set.
|
|
stream->add_track(*track);
|
|
}
|
|
|
|
// 4. Return stream.
|
|
return stream;
|
|
}
|
|
|
|
void MediaStream::initialize(JS::Realm& realm)
|
|
{
|
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(MediaStream);
|
|
Base::initialize(realm);
|
|
}
|
|
|
|
void MediaStream::visit_edges(Cell::Visitor& visitor)
|
|
{
|
|
Base::visit_edges(visitor);
|
|
for (auto& track : m_tracks)
|
|
visitor.visit(track);
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-getaudiotracks
|
|
Vector<GC::Ref<MediaStreamTrack>> MediaStream::get_audio_tracks() const
|
|
{
|
|
// The getAudioTracks method MUST return a sequence that represents a snapshot of all the MediaStreamTrack objects in this stream's track set whose [[Kind]] is equal to "audio".
|
|
Vector<GC::Ref<MediaStreamTrack>> result;
|
|
for (auto const& track : m_tracks) {
|
|
if (track->is_audio())
|
|
result.append(track);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-getvideotracks
|
|
Vector<GC::Ref<MediaStreamTrack>> MediaStream::get_video_tracks() const
|
|
{
|
|
// The getVideoTracks method MUST return a sequence that represents a snapshot of all the MediaStreamTrack objects in this stream's track set whose [[Kind]] is equal to "video".
|
|
Vector<GC::Ref<MediaStreamTrack>> result;
|
|
for (auto const& track : m_tracks) {
|
|
if (track->is_video())
|
|
result.append(track);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-gettracks
|
|
Vector<GC::Ref<MediaStreamTrack>> MediaStream::get_tracks() const
|
|
{
|
|
// The getTracks method MUST return a sequence that represents a snapshot of all the MediaStreamTrack objects in this stream's track set, regardless of [[Kind]].
|
|
return m_tracks;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-gettrackbyid
|
|
GC::Ptr<MediaStreamTrack> MediaStream::get_track_by_id(String const& track_id) const
|
|
{
|
|
// The getTrackById method MUST return either a MediaStreamTrack object from this stream's track set whose [[Id]] is equal to trackId, or null.
|
|
for (auto const& track : m_tracks) {
|
|
if (track->id() == track_id)
|
|
return track;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-addtrack
|
|
void MediaStream::add_track(GC::Ref<MediaStreamTrack> track)
|
|
{
|
|
// 1. Let track be the methods argument and stream the MediaStream object on which the method was called.
|
|
for (auto const& existing_track : m_tracks) {
|
|
|
|
// 2. If track is already in stream's track set, then abort these steps.
|
|
if (existing_track.ptr() == track.ptr())
|
|
return;
|
|
}
|
|
|
|
// 3. Add track to stream's track set.
|
|
m_tracks.append(track);
|
|
|
|
// 4. Fire a track event named addtrack with track at stream.
|
|
Bindings::MediaStreamTrackEventInit event_init {};
|
|
event_init.track = track;
|
|
auto event = MediaStreamTrackEvent::create(realm(), HTML::EventNames::addtrack, event_init);
|
|
dispatch_event(event);
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-removetrack
|
|
void MediaStream::remove_track(GC::Ref<MediaStreamTrack> track)
|
|
{
|
|
// 1. Let track be the methods argument and stream the MediaStream object on which the method was called.
|
|
// 2. If track is not in stream's track set, then abort these steps.
|
|
// 3. Remove track from stream's track set.
|
|
auto removed = m_tracks.remove_first_matching([&](auto const& existing_track) {
|
|
return existing_track.ptr() == track.ptr();
|
|
});
|
|
if (!removed)
|
|
return;
|
|
|
|
// 4. Fire a track event named removetrack with track at stream.
|
|
Bindings::MediaStreamTrackEventInit event_init;
|
|
event_init.track = track;
|
|
auto event = MediaStreamTrackEvent::create(realm(), HTML::EventNames::removetrack, event_init);
|
|
dispatch_event(event);
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-clone
|
|
GC::Ref<MediaStream> MediaStream::clone() const
|
|
{
|
|
// 1. Let streamClone be a newly constructed MediaStream object.
|
|
auto stream_clone = create(realm());
|
|
|
|
// 3. Clone each track in this MediaStream object and add the result to streamClone's track set.
|
|
for (auto const& track : m_tracks)
|
|
stream_clone->add_track(track->clone());
|
|
|
|
// 4. Return streamClone.
|
|
return stream_clone;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-active
|
|
bool MediaStream::active() const
|
|
{
|
|
// The active attribute MUST return true if this MediaStream is active and false otherwise.
|
|
for (auto const& track : m_tracks) {
|
|
if (track->ready_state() != Bindings::MediaStreamTrackState::Ended)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-onaddtrack
|
|
WebIDL::CallbackType* MediaStream::onaddtrack()
|
|
{
|
|
return event_handler_attribute(HTML::EventNames::addtrack);
|
|
}
|
|
|
|
void MediaStream::set_onaddtrack(WebIDL::CallbackType* event_handler)
|
|
{
|
|
// The event type of this event handler is addtrack.
|
|
set_event_handler_attribute(HTML::EventNames::addtrack, event_handler);
|
|
}
|
|
|
|
// https://w3c.github.io/mediacapture-main/#dom-mediastream-onremovetrack
|
|
WebIDL::CallbackType* MediaStream::onremovetrack()
|
|
{
|
|
return event_handler_attribute(HTML::EventNames::removetrack);
|
|
}
|
|
|
|
void MediaStream::set_onremovetrack(WebIDL::CallbackType* event_handler)
|
|
{
|
|
// The event type of this event handler is removetrack.
|
|
set_event_handler_attribute(HTML::EventNames::removetrack, event_handler);
|
|
}
|
|
|
|
}
|