void MediaControls::disableShowingTextTracks() { TextTrackList* trackList = mediaElement().textTracks(); for (unsigned i = 0; i < trackList->length(); ++i) { TextTrack* track = trackList->anonymousIndexedGetter(i); if (track->mode() == TextTrack::showingKeyword()) track->setMode(TextTrack::disabledKeyword()); } }
void AutomaticTrackSelection::perform(TextTrackList& textTracks) { TrackGroup captionAndSubtitleTracks(TrackGroup::CaptionsAndSubtitles); TrackGroup descriptionTracks(TrackGroup::Description); TrackGroup chapterTracks(TrackGroup::Chapter); TrackGroup metadataTracks(TrackGroup::Metadata); for (size_t i = 0; i < textTracks.length(); ++i) { TextTrack* textTrack = textTracks.item(i); if (!textTrack) continue; String kind = textTrack->kind(); TrackGroup* currentGroup; if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captionsKeyword()) { currentGroup = &captionAndSubtitleTracks; } else if (kind == TextTrack::descriptionsKeyword()) { currentGroup = &descriptionTracks; } else if (kind == TextTrack::chaptersKeyword()) { currentGroup = &chapterTracks; } else { ASSERT(kind == TextTrack::metadataKeyword()); currentGroup = &metadataTracks; } if (!currentGroup->visibleTrack && textTrack->mode() == TextTrack::showingKeyword()) currentGroup->visibleTrack = textTrack; if (!currentGroup->defaultTrack && textTrack->isDefault()) currentGroup->defaultTrack = textTrack; // Do not add this track to the group if it has already been automatically configured // as we only want to perform selection once per track so that adding another track // after the initial configuration doesn't reconfigure every track - only those that // should be changed by the new addition. For example all metadata tracks are // disabled by default, and we don't want a track that has been enabled by script // to be disabled automatically when a new metadata track is added later. if (textTrack->hasBeenConfigured()) continue; if (textTrack->language().length()) currentGroup->hasSrcLang = true; currentGroup->tracks.append(textTrack); } if (captionAndSubtitleTracks.tracks.size()) performAutomaticTextTrackSelection(captionAndSubtitleTracks); if (descriptionTracks.tracks.size()) performAutomaticTextTrackSelection(descriptionTracks); if (chapterTracks.tracks.size()) performAutomaticTextTrackSelection(chapterTracks); if (metadataTracks.tracks.size()) enableDefaultMetadataTextTracks(metadataTracks); }
void MediaControlClosedCaptionsTrackListElement::updateDisplay() { #if ENABLE(VIDEO_TRACK) DEFINE_STATIC_LOCAL(AtomicString, selectedClassValue, ("selected", AtomicString::ConstructFromLiteral)); if (!mediaController()->hasClosedCaptions()) return; HTMLMediaElement* mediaElement = toParentMediaElement(this); if (!mediaElement) return; TextTrackList* trackList = mediaElement->textTracks(); if (!trackList || !trackList->length()) return; if (m_trackListHasChanged) rebuildTrackListMenu(); bool captionsVisible = mediaElement->closedCaptionsVisible(); for (unsigned i = 0, length = m_menuItems.size(); i < length; ++i) { RefPtr<Element> trackItem = m_menuItems[i]; int trackIndex = trackListIndexForElement(trackItem.get()); if (trackIndex != HTMLMediaElement::textTracksIndexNotFound()) { if (trackIndex == HTMLMediaElement::textTracksOffIndex()) { if (captionsVisible) trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); else trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); } else { TextTrack* track = trackList->item(trackIndex); if (!track) continue; if (track->mode() == TextTrack::showingKeyword()) trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); else trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); } } } #endif }
void MediaSource::removeSourceBuffer(SourceBuffer& buffer, ExceptionCode& ec) { LOG(MediaSource, "MediaSource::removeSourceBuffer() %p", this); Ref<SourceBuffer> protect(buffer); // 2. If sourceBuffer specifies an object that is not in sourceBuffers then // throw a NOT_FOUND_ERR exception and abort these steps. if (!m_sourceBuffers->length() || !m_sourceBuffers->contains(buffer)) { ec = NOT_FOUND_ERR; return; } // 3. If the sourceBuffer.updating attribute equals true, then run the following steps: ... buffer.abortIfUpdating(); // 4. Let SourceBuffer audioTracks list equal the AudioTrackList object returned by sourceBuffer.audioTracks. RefPtr<AudioTrackList> audioTracks = buffer.audioTracks(); // 5. If the SourceBuffer audioTracks list is not empty, then run the following steps: if (audioTracks->length()) { // 5.1 Let HTMLMediaElement audioTracks list equal the AudioTrackList object returned by the audioTracks // attribute on the HTMLMediaElement. // 5.2 Let the removed enabled audio track flag equal false. bool removedEnabledAudioTrack = false; // 5.3 For each AudioTrack object in the SourceBuffer audioTracks list, run the following steps: while (audioTracks->length()) { AudioTrack* track = audioTracks->lastItem(); // 5.3.1 Set the sourceBuffer attribute on the AudioTrack object to null. track->setSourceBuffer(nullptr); // 5.3.2 If the enabled attribute on the AudioTrack object is true, then set the removed enabled // audio track flag to true. if (track->enabled()) removedEnabledAudioTrack = true; // 5.3.3 Remove the AudioTrack object from the HTMLMediaElement audioTracks list. // 5.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement audioTracks list. if (mediaElement()) mediaElement()->removeAudioTrack(track); // 5.3.5 Remove the AudioTrack object from the SourceBuffer audioTracks list. // 5.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not // cancelable, and that uses the TrackEvent interface, at the SourceBuffer audioTracks list. audioTracks->remove(track); } // 5.4 If the removed enabled audio track flag equals true, then queue a task to fire a simple event // named change at the HTMLMediaElement audioTracks list. if (removedEnabledAudioTrack) mediaElement()->audioTracks()->scheduleChangeEvent(); } // 6. Let SourceBuffer videoTracks list equal the VideoTrackList object returned by sourceBuffer.videoTracks. RefPtr<VideoTrackList> videoTracks = buffer.videoTracks(); // 7. If the SourceBuffer videoTracks list is not empty, then run the following steps: if (videoTracks->length()) { // 7.1 Let HTMLMediaElement videoTracks list equal the VideoTrackList object returned by the videoTracks // attribute on the HTMLMediaElement. // 7.2 Let the removed selected video track flag equal false. bool removedSelectedVideoTrack = false; // 7.3 For each VideoTrack object in the SourceBuffer videoTracks list, run the following steps: while (videoTracks->length()) { VideoTrack* track = videoTracks->lastItem(); // 7.3.1 Set the sourceBuffer attribute on the VideoTrack object to null. track->setSourceBuffer(nullptr); // 7.3.2 If the selected attribute on the VideoTrack object is true, then set the removed selected // video track flag to true. if (track->selected()) removedSelectedVideoTrack = true; // 7.3.3 Remove the VideoTrack object from the HTMLMediaElement videoTracks list. // 7.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement videoTracks list. if (mediaElement()) mediaElement()->removeVideoTrack(track); // 7.3.5 Remove the VideoTrack object from the SourceBuffer videoTracks list. // 7.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not // cancelable, and that uses the TrackEvent interface, at the SourceBuffer videoTracks list. videoTracks->remove(track); } // 7.4 If the removed selected video track flag equals true, then queue a task to fire a simple event // named change at the HTMLMediaElement videoTracks list. if (removedSelectedVideoTrack) mediaElement()->videoTracks()->scheduleChangeEvent(); } // 8. Let SourceBuffer textTracks list equal the TextTrackList object returned by sourceBuffer.textTracks. RefPtr<TextTrackList> textTracks = buffer.textTracks(); // 9. If the SourceBuffer textTracks list is not empty, then run the following steps: if (textTracks->length()) { // 9.1 Let HTMLMediaElement textTracks list equal the TextTrackList object returned by the textTracks // attribute on the HTMLMediaElement. // 9.2 Let the removed enabled text track flag equal false. bool removedEnabledTextTrack = false; // 9.3 For each TextTrack object in the SourceBuffer textTracks list, run the following steps: while (textTracks->length()) { TextTrack* track = textTracks->lastItem(); // 9.3.1 Set the sourceBuffer attribute on the TextTrack object to null. track->setSourceBuffer(nullptr); // 9.3.2 If the mode attribute on the TextTrack object is set to "showing" or "hidden", then // set the removed enabled text track flag to true. if (track->mode() == TextTrack::showingKeyword() || track->mode() == TextTrack::hiddenKeyword()) removedEnabledTextTrack = true; // 9.3.3 Remove the TextTrack object from the HTMLMediaElement textTracks list. // 9.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement textTracks list. if (mediaElement()) mediaElement()->removeTextTrack(track); // 9.3.5 Remove the TextTrack object from the SourceBuffer textTracks list. // 9.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not // cancelable, and that uses the TrackEvent interface, at the SourceBuffer textTracks list. textTracks->remove(track); } // 9.4 If the removed enabled text track flag equals true, then queue a task to fire a simple event // named change at the HTMLMediaElement textTracks list. if (removedEnabledTextTrack) mediaElement()->textTracks()->scheduleChangeEvent(); } // 10. If sourceBuffer is in activeSourceBuffers, then remove sourceBuffer from activeSourceBuffers ... m_activeSourceBuffers->remove(buffer); // 11. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer event // on that object. m_sourceBuffers->remove(buffer); // 12. Destroy all resources for sourceBuffer. buffer.removedFromMediaSource(); }
void AutomaticTrackSelection::performAutomaticTextTrackSelection(const TrackGroup& group) { ASSERT(group.tracks.size()); // First, find the track in the group that should be enabled (if any). HeapVector<Member<TextTrack>> currentlyEnabledTracks; TextTrack* trackToEnable = nullptr; TextTrack* defaultTrack = nullptr; TextTrack* preferredTrack = nullptr; TextTrack* fallbackTrack = nullptr; int highestTrackScore = 0; for (size_t i = 0; i < group.tracks.size(); ++i) { TextTrack* textTrack = group.tracks[i]; if (m_configuration.disableCurrentlyEnabledTracks && textTrack->mode() == TextTrack::showingKeyword()) currentlyEnabledTracks.append(textTrack); int trackScore = textTrackSelectionScore(*textTrack); if (textTrack->kind() == preferredTrackKind()) trackScore += 1; if (trackScore) { // * If the text track kind is subtitles or captions and the user has indicated an interest in having a // track with this text track kind, text track language, and text track label enabled, and there is no // other text track in the media element's list of text tracks with a text track kind of either subtitles // or captions whose text track mode is showing // Let the text track mode be showing. if (trackScore > highestTrackScore) { preferredTrack = textTrack; highestTrackScore = trackScore; } if (!defaultTrack && textTrack->isDefault()) defaultTrack = textTrack; if (!fallbackTrack) fallbackTrack = textTrack; } else if (!group.visibleTrack && !defaultTrack && textTrack->isDefault()) { // * If the track element has a default attribute specified, and there is no other text track in the media // element's list of text tracks whose text track mode is showing or showing by default // Let the text track mode be showing by default. defaultTrack = textTrack; } } if (m_configuration.textTrackKindUserPreference != TextTrackKindUserPreference::Default) trackToEnable = preferredTrack; if (!trackToEnable && defaultTrack) trackToEnable = defaultTrack; if (!trackToEnable && m_configuration.forceEnableSubtitleOrCaptionTrack && group.kind == TrackGroup::CaptionsAndSubtitles) { if (fallbackTrack) trackToEnable = fallbackTrack; else trackToEnable = group.tracks[0]; } if (currentlyEnabledTracks.size()) { for (size_t i = 0; i < currentlyEnabledTracks.size(); ++i) { TextTrack* textTrack = currentlyEnabledTracks[i]; if (textTrack != trackToEnable) textTrack->setMode(TextTrack::disabledKeyword()); } } if (trackToEnable) trackToEnable->setMode(TextTrack::showingKeyword()); }
static v8::Handle<v8::Value> modeAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { TextTrack* imp = V8TextTrack::toNative(info.Holder()); return v8String(imp->mode(), info.GetIsolate()); }