// - return the empty string if type is a type that the user agent knows it cannot render or is the type "application/octet-stream"
// - return "probably" if the user agent is confident that the type represents a media resource that it can render if used in with this audio or video element
// - return "maybe" otherwise. Implementers are encouraged to return "maybe" unless the type can be confidently established as being supported or not
// Generally, a user agent should never return "probably" for a type that allows the codecs parameter if that parameter is not present.
if(type=="application/octet-stream"sv)
returnBindings::CanPlayTypeResult::Empty;
// FIXME: Eventually we should return `Maybe` here, but for now `Empty` is our best bet :^)
// Being honest here leads to some apps and frameworks skipping things like audio loading,
// which for the time being would create more issues than it solves - e.g. endless waiting
// 8. Return. The element won't attempt to load another resource until this algorithm is triggered again.
return{};
}
// -> Otherwise (mode is children)
caseSelectMode::Children:
// FIXME: 1. ⌛ Let pointer be a position defined by two adjacent nodes in the media element's child list, treating the start of the list (before the
// first child in the list, if any) and end of the list (after the last child in the list, if any) as nodes in their own right. One node is
// the node before pointer, and the other node is the node after pointer. Initially, let pointer be the position between the candidate node
// and the next node, if there are any, or the end of the list, if it is the last node.
//
// As nodes are inserted and removed into the media element, pointer must be updated as follows:
//
// If a new node is inserted between the two nodes that define pointer
// Let pointer be the point between the node before pointer and the new node. In other words, insertions at pointer go after pointer.
// If the node before pointer is removed
// Let pointer be the point between the node after pointer and the node before the node after pointer. In other words, pointer doesn't
// move relative to the remaining nodes.
// If the node after pointer is removed
// Let pointer be the point between the node before pointer and the node after the node before pointer. Just as with the previous case,
// pointer doesn't move relative to the remaining nodes.
// Other changes don't affect pointer.
// FIXME: 2. ⌛ Process candidate: If candidate does not have a src attribute, or if its src attribute's value is the empty string, then end the
// synchronous section, and jump down to the failed with elements step below.
// FIXME: 3. ⌛ Let urlString and urlRecord be the resulting URL string and the resulting URL record, respectively, that would have resulted from parsing
// the URL specified by candidate's src attribute's value relative to the candidate's node document when the src attribute was last changed.
// FIXME: 4. ⌛ If urlString was not obtained successfully, then end the synchronous section, and jump down to the failed with elements step below.
// FIXME: 5. ⌛ If candidate has a type attribute whose value, when parsed as a MIME type (including any codecs described by the codecs parameter, for
// types that define that parameter), represents a type that the user agent knows it cannot render, then end the synchronous section, and
// jump down to the failed with elements step below.
// FIXME: 6. ⌛ Set the currentSrc attribute to urlString.
// FIXME: 7. End the synchronous section, continuing the remaining steps in parallel.
// FIXME: 8. Run the resource fetch algorithm with urlRecord. If that algorithm returns without aborting this one, then the load failed.
// FIXME: 9. Failed with elements: Queue a media element task given the media element to fire an event named error at candidate.
// FIXME: 10. Await a stable state. The synchronous section consists of all the remaining steps of this algorithm until the algorithm says the
// synchronous section has ended. (Steps in synchronous sections are marked with ⌛.)
// FIXME: 11. ⌛ Forget the media element's media-resource-specific tracks.
// FIXME: 12. ⌛ Find next candidate: Let candidate be null.
// FIXME: 13. ⌛ Search loop: If the node after pointer is the end of the list, then jump to the waiting step below.
// FIXME: 14. ⌛ If the node after pointer is a source element, let candidate be that element.
// FIXME: 15. ⌛ Advance pointer so that the node before pointer is now the node that was after pointer, and the node after pointer is the node after
// the node that used to be after pointer, if any.
// FIXME: 16. ⌛ If candidate is null, jump back to the search loop step. Otherwise, jump back to the process candidate step.
// FIXME: 17. ⌛ Waiting: Set the element's networkState attribute to the NETWORK_NO_SOURCE value.
// FIXME: 18. ⌛ Set the element's show poster flag to true.
// FIXME: 19. ⌛ Queue a media element task given the media element to set the element's delaying-the-load-event flag to false. This stops delaying the
// load event.
// FIXME: 20. End the synchronous section, continuing the remaining steps in parallel.
// FIXME: 21. Wait until the node after pointer is a node other than the end of the list. (This step might wait forever.)
// FIXME: 22. Await a stable state. The synchronous section consists of all the remaining steps of this algorithm until the algorithm says the
// synchronous section has ended. (Steps in synchronous sections are marked with ⌛.)
// FIXME: 23. ⌛ Set the element's delaying-the-load-event flag back to true (this delays the load event again, in case it hasn't been fired yet).
// FIXME: 24. ⌛ Set the networkState back to NETWORK_LOADING.
// FIXME: 25. ⌛ Jump back to the find next candidate step above.
// 1. If the algorithm was invoked with media provider object or a URL record whose blob URL entry is a blob URL entry whose object is a media provider
// object, then let mode be local. Otherwise let mode be remote.
// FIXME: Detect media provider object / blob URLs with a media provider object.
automode=FetchMode::Remote;
// FIXME: 2. If mode is remote, then let the current media resource be the resource given by the URL record passed to this algorithm; otherwise, let the
// current media resource be the resource given by the media provider object. Either way, the current media resource is now the element's media
// resource.
// FIXME: 3. Remove all media-resource-specific text tracks from the media element's list of pending text tracks, if any.
// 4. Run the appropriate steps from the following list:
switch(mode){
// -> If mode is remote
caseFetchMode::Remote:{
// FIXME: 1. Optionally, run the following substeps. This is the expected behavior if the user agent intends to not attempt to fetch the resource until
// the user requests it explicitly (e.g. as a way to implement the preload attribute's none keyword).
// 1. Set the networkState to NETWORK_IDLE.
// 2. Queue a media element task given the media element to fire an event named suspend at the element.
// 3. Queue a media element task given the media element to set the element's delaying-the-load-event flag to false. This stops delaying
// the load event.
// 4. Wait for the task to be run.
// 5. Wait for an implementation-defined event (e.g., the user requesting that the media element begin playback).
// 6. Set the element's delaying-the-load-event flag back to true (this delays the load event again, in case it hasn't been fired yet).
// 7. Set the networkState to NETWORK_LOADING.
// 2. Let destination be "audio" if the media element is an audio element, or "video" otherwise.
// FIXME: 1. Create an AudioTrack object to represent the audio track.
// FIXME: 2. Update the media element's audioTracks attribute's AudioTrackList object with the new AudioTrack object.
// FIXME: 3. Let enable be unknown.
// FIXME: 4. If either the media resource or the URL of the current media resource indicate a particular set of audio tracks to enable, or if
// the user agent has information that would facilitate the selection of specific audio tracks to improve the user's experience, then:
// if this audio track is one of the ones to enable, then set enable to true, otherwise, set enable to false.
// FIXME: 5. If enable is still unknown, then, if the media element does not yet have an enabled audio track, then set enable to true, otherwise,
// set enable to false.
// FIXME: 6. If enable is true, then enable this audio track, otherwise, do not enable this audio track.
// FIXME: 7. Fire an event named addtrack at this AudioTrackList object, using TrackEvent, with the track attribute initialized to the new AudioTrack object.
}
// -> If the media resource is found to have a video track
// -> Once enough of the media data has been fetched to determine the duration of the media resource, its dimensions, and other metadata
if(video_track!=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).
// FIXME: 3. Set the current playback position and the official playback position to the earliest possible position.
// FIXME: 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.
// 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.
if(is<HTMLVideoElement>(*this)){
// FIXME: Set the videoWidth and videoHeight attributes.
// FIXME: 6. Set the readyState attribute to HAVE_METADATA.
// FIXME: 7. Let jumped be false.
// FIXME: 8. If the media element's default playback start position is greater than zero, then seek to that time, and let jumped be true.
// FIXME: 9. Let the media element's default playback start position be zero.
// FIXME: 10. Let the initial playback position be zero.
// FIXME: 11. If either the media resource or the URL of the current media resource indicate a particular start time, then set the initial playback
// position to that time and, if jumped is still false, seek to that time.
// FIXME: 12. If there is no enabled audio track, then enable an audio track. This will cause a change event to be fired.
// 13. If there is no selected video track, then select a video track. This will cause a change event to be fired.
if(m_video_tracks->selected_index()==-1)
video_track->set_selected(true);
// FIXME: Once the readyState attribute reaches HAVE_CURRENT_DATA, after the loadeddata event has been fired, set the element's delaying-the-load-event
// flag to false. This stops delaying the load event.
}
// -> Once the entire media resource has been fetched (but potentially before any of it has been decoded)
if(video_track!=nullptr){
// Fire an event named progress at the media element.