Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/HTML/HTMLMediaElement.cpp (C++)

Code before:

    // 5. If enable is still unknown, then, if the media element does not yet have a selected video track, then set enable to true, otherwise, set
    //    enable to false.
    if (enable == TriState::Unknown)
        enable = m_video_tracks->selected_index() == -1 ? TriState::True : TriState::False;

    // 6. If enable is true, then select this track and unselect any previously selected video tracks, otherwise, do not select this video track.
    //    If other tracks are unselected, then a change event will be fired.
    if (enable == TriState::True)
        video_track->set_selected(true);

    // NB: See the comment regarding AudioTrack.kind above with regard to https://dev.w3.org/html5/html-sourcing-inband-tracks/.
    video_track->set_kind(enable == TriState::True ? "main"_utf16 : "translation"_utf16);

    // 7. Fire an event named addtrack at this VideoTrackList object, using TrackEvent, with the track attribute initialized to the new VideoTrack object.
    TrackEventInit event_init {};
    event_init.track = GC::make_root(video_track);

    auto event = TrackEvent::create(realm, HTML::EventNames::addtrack, move(event_init));
    m_video_tracks->dispatch_event(event);
}

void HTMLMediaElement::on_metadata_parsed(AK::Duration const& duration)
{
    update_volume();

    // AD-HOC: After selecting a track, we do not need the source element selector anymore.
    m_source_element_selector = nullptr;

    // FIXME: 1. Establish the media timeline for the purposes of the current playback position and the earliest possible position, based on the media data.
    // FIXME: 2. Update the timeline offset to the date and time that corresponds to the zero time in the media timeline established in the previous step,
    //           if any. If no explicit time and date is given by the media resource, the timeline offset must be set to Not-a-Number (NaN).

    // 3. Set the current playback position and the official playback position to the earliest possible position.
    m_current_playback_position = 0;
    m_official_playback_position = 0;

    // 4. Update the duration attribute with the time of the last frame of the resource, if known, on the media timeline established above. If it is
    //    not known (e.g. a stream that is in principle infinite), update the duration attribute to the value positive Infinity.
    // FIXME: Handle unbounded media resources.
    set_duration(duration.to_seconds_f64());

    // 5. For video elements, set the videoWidth and videoHeight attributes, and queue a media element task given the media element to fire an event
    //    named resize at the media element.
    auto* video_element = as_if<HTMLVideoElement>(*this);
    if (m_selected_video_track && video_element) {
        video_element->set_video_height(m_selected_video_track->track_in_playback_manager().video_data().pixel_height);
        video_element->set_video_width(m_selected_video_track->track_in_playback_manager().video_data().pixel_width);

        queue_a_media_element_task([this] {
            dispatch_event(DOM::Event::create(this->realm(), HTML::EventNames::resize));

Review comment (refactor):
As a note to me to fix this later, could we add a FIXME to move this to setup_playback_manager? I know it won't work there at the moment, since it only sets the volume if the audio sink exists, but we can make it so that we store volume in PlaybackManager and set it upon creating the mixing sink instead.

Code after:

    // 5. If enable is still unknown, then, if the media element does not yet have a selected video track, then set enable to true, otherwise, set
    //    enable to false.
    if (enable == TriState::Unknown)
        enable = m_video_tracks->selected_index() == -1 ? TriState::True : TriState::False;

    // 6. If enable is true, then select this track and unselect any previously selected video tracks, otherwise, do not select this video track.
    //    If other tracks are unselected, then a change event will be fired.
    if (enable == TriState::True)
        video_track->set_selected(true);

    // NB: See the comment regarding AudioTrack.kind above with regard to https://dev.w3.org/html5/html-sourcing-inband-tracks/.
    video_track->set_kind(enable == TriState::True ? "main"_utf16 : "translation"_utf16);

    // 7. Fire an event named addtrack at this VideoTrackList object, using TrackEvent, with the track attribute initialized to the new VideoTrack object.
    TrackEventInit event_init {};
    event_init.track = GC::make_root(video_track);

    auto event = TrackEvent::create(realm, HTML::EventNames::addtrack, move(event_init));
    m_video_tracks->dispatch_event(event);
}

void HTMLMediaElement::on_metadata_parsed()
{
    // FIXME: Move this to setup_playback_manager()
    update_volume();

    // AD-HOC: After selecting a track, we do not need the source element selector anymore.
    m_source_element_selector = nullptr;

    // FIXME: 1. Establish the media timeline for the purposes of the current playback position and the earliest possible position, based on the media data.
    // FIXME: 2. Update the timeline offset to the date and time that corresponds to the zero time in the media timeline established in the previous step,
    //           if any. If no explicit time and date is given by the media resource, the timeline offset must be set to Not-a-Number (NaN).

    // 3. Set the current playback position and the official playback position to the earliest possible position.
    m_current_playback_position = 0;
    m_official_playback_position = 0;

    // 4. Update the duration attribute with the time of the last frame of the resource, if known, on the media timeline established above. If it is
    //    not known (e.g. a stream that is in principle infinite), update the duration attribute to the value positive Infinity.
    // FIXME: Handle unbounded media resources.
    set_duration(m_playback_manager->duration().to_seconds_f64());

    // 5. For video elements, set the videoWidth and videoHeight attributes, and queue a media element task given the media element to fire an event
    //    named resize at the media element.
    auto* video_element = as_if<HTMLVideoElement>(*this);
    if (m_selected_video_track && video_element) {
        video_element->set_video_height(m_selected_video_track->track_in_playback_manager().video_data().pixel_height);
        video_element->set_video_width(m_selected_video_track->track_in_playback_manager().video_data().pixel_width);

        queue_a_media_element_task([this] {