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 MediaControls::showTextTrackAtIndex(unsigned indexToEnable) { TextTrackList* trackList = mediaElement().textTracks(); if (indexToEnable >= trackList->length()) return; TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable); if (track && track->canBeRendered()) track->setMode(TextTrack::showingKeyword()); }
void MediaControlClosedCaptionsTrackListElement::updateDisplay() { #if ENABLE(VIDEO_TRACK) DEFINE_STATIC_LOCAL(AtomicString, selectedClassValue, ("selected", AtomicString::ConstructFromLiteral)); if (!mediaController()->hasClosedCaptions()) return; if (!document()->page()) return; CaptionUserPreferences::CaptionDisplayMode displayMode = document()->page()->group().captionPreferences()->captionDisplayMode(); bool trackIsSelected = displayMode != CaptionUserPreferences::Automatic && displayMode != CaptionUserPreferences::ForcedOnly; HTMLMediaElement* mediaElement = toParentMediaElement(this); if (!mediaElement) return; TextTrackList* trackList = mediaElement->textTracks(); if (!trackList || !trackList->length()) return; rebuildTrackListMenu(); for (unsigned i = 0, length = m_menuItems.size(); i < length; ++i) { RefPtr<Element> trackItem = m_menuItems[i]; RefPtr<TextTrack> textTrack; MenuItemToTrackMap::iterator iter = m_menuToTrackMap.find(trackItem.get()); if (iter == m_menuToTrackMap.end()) continue; textTrack = iter->value; if (!textTrack) continue; if (textTrack == TextTrack::captionMenuOffItem()) { if (displayMode == CaptionUserPreferences::ForcedOnly) trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); else trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); continue; } if (textTrack == TextTrack::captionMenuAutomaticItem()) { if (displayMode == CaptionUserPreferences::Automatic) trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); else trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); continue; } if (trackIsSelected && textTrack->mode() == TextTrack::showingKeyword()) trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); else trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); } #endif }
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 JSTextTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSTextTrackList* jsTextTrackList = jsCast<JSTextTrackList*>(cell); ASSERT_GC_OBJECT_INHERITS(jsTextTrackList, info()); COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); ASSERT(jsTextTrackList->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(jsTextTrackList, visitor); TextTrackList* textTrackList = static_cast<TextTrackList*>(jsTextTrackList->impl()); visitor.addOpaqueRoot(root(textTrackList->element())); textTrackList->visitJSEventListeners(visitor); }
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 MediaControlClosedCaptionsTrackListElement::rebuildTrackListMenu() { #if ENABLE(VIDEO_TRACK) // Remove any existing content. removeChildren(); m_menuItems.clear(); m_menuToTrackMap.clear(); if (!mediaController()->hasClosedCaptions()) return; HTMLMediaElement* mediaElement = toParentMediaElement(this); if (!mediaElement) return; TextTrackList* trackList = mediaElement->textTracks(); if (!trackList || !trackList->length()) return; Document* doc = document(); if (!document()->page()) return; CaptionUserPreferences* captionPreferences = document()->page()->group().captionPreferences(); Vector<RefPtr<TextTrack> > tracksForMenu = captionPreferences->sortedTrackListForMenu(trackList); RefPtr<Element> captionsHeader = doc->createElement(h3Tag, ASSERT_NO_EXCEPTION); captionsHeader->appendChild(doc->createTextNode(textTrackSubtitlesText())); appendChild(captionsHeader); RefPtr<Element> captionsMenuList = doc->createElement(ulTag, ASSERT_NO_EXCEPTION); for (unsigned i = 0, length = tracksForMenu.size(); i < length; ++i) { RefPtr<TextTrack> textTrack = tracksForMenu[i]; RefPtr<Element> menuItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION); menuItem->appendChild(doc->createTextNode(captionPreferences->displayNameForTrack(textTrack.get()))); captionsMenuList->appendChild(menuItem); m_menuItems.append(menuItem); m_menuToTrackMap.add(menuItem, textTrack); } appendChild(captionsMenuList); #endif }
void MediaControlTextTrackListElement::refreshTextTrackListMenu() { if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreReady()) return; EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents; removeChildren(OmitSubtreeModifiedEvent); // Construct a menu for subtitles and captions // Pass in a nullptr to createTextTrackListItem to create the "Off" track item. appendChild(createTextTrackListItem(nullptr)); TextTrackList* trackList = mediaElement().textTracks(); for (unsigned i = 0; i < trackList->length(); i++) { TextTrack* track = trackList->anonymousIndexedGetter(i); if (!track->canBeRendered()) continue; appendChild(createTextTrackListItem(track)); } }
void MediaControlClosedCaptionsTrackListElement::rebuildTrackListMenu() { #if ENABLE(VIDEO_TRACK) // Remove any existing content. removeChildren(); m_menuItems.clear(); m_trackListHasChanged = false; if (!mediaController()->hasClosedCaptions()) return; HTMLMediaElement* mediaElement = toParentMediaElement(this); if (!mediaElement) return; TextTrackList* trackList = mediaElement->textTracks(); if (!trackList || !trackList->length()) return; Document* doc = document(); RefPtr<Element> captionsSection = doc->createElement(sectionTag, ASSERT_NO_EXCEPTION); RefPtr<Element> captionsHeader = doc->createElement(h3Tag, ASSERT_NO_EXCEPTION); captionsHeader->appendChild(doc->createTextNode(textTrackClosedCaptionsText())); captionsSection->appendChild(captionsHeader); RefPtr<Element> captionsMenuList = doc->createElement(ulTag, ASSERT_NO_EXCEPTION); RefPtr<Element> subtitlesSection = doc->createElement(sectionTag, ASSERT_NO_EXCEPTION); RefPtr<Element> subtitlesHeader = doc->createElement(h3Tag, ASSERT_NO_EXCEPTION); subtitlesHeader->appendChild(doc->createTextNode(textTrackSubtitlesText())); subtitlesSection->appendChild(subtitlesHeader); RefPtr<Element> subtitlesMenuList = doc->createElement(ulTag, ASSERT_NO_EXCEPTION); RefPtr<Element> trackItem; trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION); trackItem->appendChild(doc->createTextNode(textTrackOffText())); trackItem->setAttribute(trackIndexAttributeName(), textTracksOffAttrValue, ASSERT_NO_EXCEPTION); captionsMenuList->appendChild(trackItem); m_menuItems.append(trackItem); trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION); trackItem->appendChild(doc->createTextNode(textTrackOffText())); trackItem->setAttribute(trackIndexAttributeName(), textTracksOffAttrValue, ASSERT_NO_EXCEPTION); subtitlesMenuList->appendChild(trackItem); m_menuItems.append(trackItem); bool hasCaptions = false; bool hasSubtitles = false; for (unsigned i = 0, length = trackList->length(); i < length; ++i) { TextTrack* track = trackList->item(i); trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION); // Add a custom attribute to the <li> element which will allow // us to easily associate the user tapping here with the // track. Since this list is rebuilt if the tracks change, we // should always be in sync. trackItem->setAttribute(trackIndexAttributeName(), String::number(i), ASSERT_NO_EXCEPTION); AtomicString labelText = track->label(); if (labelText.isNull() || labelText.isEmpty()) labelText = displayNameForLanguageLocale(track->language()); if (labelText.isNull() || labelText.isEmpty()) labelText = textTrackNoLabelText(); trackItem->appendChild(doc->createTextNode(labelText)); if (track->kind() == track->captionsKeyword()) { hasCaptions = true; insertTextTrackMenuItemIntoSortedContainer(trackItem, captionsMenuList); } if (track->kind() == track->subtitlesKeyword()) { hasSubtitles = true; insertTextTrackMenuItemIntoSortedContainer(trackItem, subtitlesMenuList); } m_menuItems.append(trackItem); } captionsSection->appendChild(captionsMenuList); subtitlesSection->appendChild(subtitlesMenuList); if (hasCaptions) appendChild(captionsSection); if (hasSubtitles) appendChild(subtitlesSection); updateDisplay(); #endif }
bool LessThan(SimpleTextTrackEvent* aOne, SimpleTextTrackEvent* aTwo) const { // TimeMarchesOn step 13.1. if (aOne->mTime < aTwo->mTime) { return true; } else if (aOne->mTime > aTwo->mTime) { return false; } // TimeMarchesOn step 13.2 text track cue order. // TextTrack position in TextTrackList TextTrack* t1 = aOne->mTrack; TextTrack* t2 = aTwo->mTrack; MOZ_ASSERT(t1, "CompareSimpleTextTrackEvents t1 is null"); MOZ_ASSERT(t2, "CompareSimpleTextTrackEvents t2 is null"); if (t1 != t2) { TextTrackList* tList = t1->GetTextTrackList(); MOZ_ASSERT(tList, "CompareSimpleTextTrackEvents tList is null"); nsTArray<RefPtr<TextTrack>>& textTracks = tList->GetTextTrackArray(); auto index1 = textTracks.IndexOf(t1); auto index2 = textTracks.IndexOf(t2); if (index1 < index2) { return true; } else if (index1 > index2) { return false; } } MOZ_ASSERT(t1 == t2, "CompareSimpleTextTrackEvents t1 != t2"); // c1 and c2 are both belongs to t1. TextTrackCue* c1 = aOne->mCue; TextTrackCue* c2 = aTwo->mCue; if (c1 != c2) { if (c1->StartTime() < c2->StartTime()) { return true; } else if (c1->StartTime() > c2->StartTime()) { return false; } if (c1->EndTime() < c2->EndTime()) { return true; } else if (c1->EndTime() > c2->EndTime()) { return false; } TextTrackCueList* cueList = t1->GetCues(); MOZ_ASSERT(cueList); nsTArray<RefPtr<TextTrackCue>>& cues = cueList->GetCuesArray(); auto index1 = cues.IndexOf(c1); auto index2 = cues.IndexOf(c2); if (index1 < index2) { return true; } else if (index1 > index2) { return false; } } // TimeMarchesOn step 13.3. if (aOne->mName.EqualsLiteral("enter") || aTwo->mName.EqualsLiteral("exit")) { return true; } return false; }